15 Commits

Author SHA1 Message Date
a0e7a898fa Fixed double entry issue 2026-08-30 21:06:46 +05:30
eb39d5ff90 Web approach uniformity done 2026-08-30 19:54:54 +05:30
372c2bc14d Web approach - basic look and feel done 2026-08-29 21:52:11 +05:30
364961c9de Update auth_screen.dart 2026-08-29 17:24:08 +05:30
cdc58c9bce Revamp Done - Support for Individual and Jwellery module added 2026-08-29 12:01:00 +05:30
eacca6aaea Fixed upto purchases and rate sync process 2026-08-28 19:45:19 +05:30
189f49ed07 Done Category, Product Catalogue, Customer, Vendor, Purchase Invoice Module 2026-08-28 11:30:18 +05:30
0d13833679 Individual and Jwellery Account Setup done 2026-08-25 22:19:10 +05:30
53c1f62373 Revamp stage one - individual account and account setup fixed 2026-08-25 19:45:24 +05:30
82c1a891c0 Project management bug fixes 2026-08-24 23:23:01 +05:30
2a106a8716 Project management related changes 2026-08-24 22:57:06 +05:30
71b2389221 Fixed UI issue 2026-08-24 18:38:46 +05:30
fc0faafa18 Fixed bugs 2026-08-20 22:02:38 +05:30
5f620022f3 Inventory Management | Customer Management | Invoice Management Done | Commodity Rate Sync Done 2026-08-20 20:35:41 +05:30
ba9a9fd8a4 Product Add Done 2026-08-16 22:51:34 +05:30
311 changed files with 38891 additions and 2557 deletions

BIN
.DS_Store vendored

Binary file not shown.

File diff suppressed because it is too large Load Diff

579
analyze_output.txt Normal file
View File

@@ -0,0 +1,579 @@
Analyzing Kifi...
warning • Unused import: 'dart:convert' • kifi-api/scratch.dart:1:8 • unused_import
error • Target of URI doesn't exist: 'package:http/http.dart' • kifi-api/scratch.dart:2:8 • uri_does_not_exist
warning • The value of the local variable 'token' isn't used • kifi-api/scratch.dart:5:9 • unused_local_variable
info • 'withOpacity' is deprecated and shouldn't be used. Use .withValues() to avoid precision loss • kifi-app/lib/core/theme/app_theme.dart:42:53 • deprecated_member_use
info • 'withOpacity' is deprecated and shouldn't be used. Use .withValues() to avoid precision loss • kifi-app/lib/core/theme/app_theme.dart:46:53 • deprecated_member_use
info • 'withOpacity' is deprecated and shouldn't be used. Use .withValues() to avoid precision loss • kifi-app/lib/core/theme/app_theme.dart:98:53 • deprecated_member_use
info • 'withOpacity' is deprecated and shouldn't be used. Use .withValues() to avoid precision loss • kifi-app/lib/core/theme/app_theme.dart:102:53 • deprecated_member_use
warning • Unused import: 'package:shared_preferences/shared_preferences.dart' • kifi-app/lib/core/theme/theme_provider.dart:3:8 • unused_import
warning • The value of the field '_themePrefKey' isn't used • kifi-app/lib/core/theme/theme_provider.dart:6:16 • unused_field
info • 'withOpacity' is deprecated and shouldn't be used. Use .withValues() to avoid precision loss • kifi-app/lib/core/widgets/smart_search_dropdown.dart:196:81 • deprecated_member_use
warning • Dead code • kifi-app/lib/core/widgets/smart_search_dropdown.dart:228:65 • dead_code
warning • The left operand can't be null, so the right operand is never executed • kifi-app/lib/core/widgets/smart_search_dropdown.dart:228:68 • dead_null_aware_expression
info • Don't invoke 'print' in production code • kifi-app/lib/features/auth/presentation/auth_screen.dart:46:11 • avoid_print
info • Don't invoke 'print' in production code • kifi-app/lib/features/auth/presentation/auth_screen.dart:48:11 • avoid_print
info • Don't invoke 'print' in production code • kifi-app/lib/features/auth/presentation/auth_screen.dart:61:11 • avoid_print
info • Statements in an if should be enclosed in a block • kifi-app/lib/features/auth/presentation/auth_screen.dart:63:13 • curly_braces_in_flow_control_structures
info • 'withOpacity' is deprecated and shouldn't be used. Use .withValues() to avoid precision loss • kifi-app/lib/features/auth/presentation/auth_screen.dart:187:63 • deprecated_member_use
info • 'withOpacity' is deprecated and shouldn't be used. Use .withValues() to avoid precision loss • kifi-app/lib/features/auth/presentation/auth_screen.dart:223:63 • deprecated_member_use
info • 'withOpacity' is deprecated and shouldn't be used. Use .withValues() to avoid precision loss • kifi-app/lib/features/auth/presentation/forgot_password_screen.dart:111:63 • deprecated_member_use
info • 'withOpacity' is deprecated and shouldn't be used. Use .withValues() to avoid precision loss • kifi-app/lib/features/auth/presentation/otp_screen.dart:76:63 • deprecated_member_use
info • The import of 'package:cross_file/cross_file.dart' is unnecessary because all of the used elements are also provided by the import of 'package:share_plus/share_plus.dart' • kifi-app/lib/features/auth/presentation/profile_screen.dart:9:8 • unnecessary_import
info • The imported package 'cross_file' isn't a dependency of the importing package • kifi-app/lib/features/auth/presentation/profile_screen.dart:9:8 • depend_on_referenced_packages
warning • Unused import: '../providers/auth_provider.dart' • kifi-app/lib/features/auth/presentation/profile_screen.dart:12:8 • unused_import
warning • Unused import: '../../projects/providers/project_mode_provider.dart' • kifi-app/lib/features/auth/presentation/profile_screen.dart:16:8 • unused_import
info • Statements in an if should be enclosed in a block • kifi-app/lib/features/auth/presentation/profile_screen.dart:79:7 • curly_braces_in_flow_control_structures
info • 'Share' is deprecated and shouldn't be used. Use SharePlus instead • kifi-app/lib/features/auth/presentation/profile_screen.dart:108:13 • deprecated_member_use
info • 'shareXFiles' is deprecated and shouldn't be used. Use SharePlus.instance.share() instead • kifi-app/lib/features/auth/presentation/profile_screen.dart:108:19 • deprecated_member_use
info • Statements in an if should be enclosed in a block • kifi-app/lib/features/auth/presentation/profile_screen.dart:113:9 • curly_braces_in_flow_control_structures
info • 'withOpacity' is deprecated and shouldn't be used. Use .withValues() to avoid precision loss • kifi-app/lib/features/auth/presentation/profile_screen.dart:142:64 • deprecated_member_use
info • 'withOpacity' is deprecated and shouldn't be used. Use .withValues() to avoid precision loss • kifi-app/lib/features/auth/presentation/profile_screen.dart:158:37 • deprecated_member_use
info • 'withOpacity' is deprecated and shouldn't be used. Use .withValues() to avoid precision loss • kifi-app/lib/features/auth/presentation/profile_screen.dart:170:38 • deprecated_member_use
info • 'withOpacity' is deprecated and shouldn't be used. Use .withValues() to avoid precision loss • kifi-app/lib/features/auth/presentation/profile_screen.dart:199:48 • deprecated_member_use
info • 'withOpacity' is deprecated and shouldn't be used. Use .withValues() to avoid precision loss • kifi-app/lib/features/auth/presentation/profile_screen.dart:200:48 • deprecated_member_use
info • 'withOpacity' is deprecated and shouldn't be used. Use .withValues() to avoid precision loss • kifi-app/lib/features/auth/presentation/profile_screen.dart:207:55 • deprecated_member_use
info • 'withOpacity' is deprecated and shouldn't be used. Use .withValues() to avoid precision loss • kifi-app/lib/features/auth/presentation/profile_screen.dart:259:43 • deprecated_member_use
info • 'withOpacity' is deprecated and shouldn't be used. Use .withValues() to avoid precision loss • kifi-app/lib/features/auth/presentation/profile_screen.dart:262:53 • deprecated_member_use
info • 'withOpacity' is deprecated and shouldn't be used. Use .withValues() to avoid precision loss • kifi-app/lib/features/auth/presentation/profile_screen.dart:333:67 • deprecated_member_use
info • 'withOpacity' is deprecated and shouldn't be used. Use .withValues() to avoid precision loss • kifi-app/lib/features/auth/presentation/profile_screen.dart:423:49 • deprecated_member_use
info • 'withOpacity' is deprecated and shouldn't be used. Use .withValues() to avoid precision loss • kifi-app/lib/features/auth/presentation/profile_screen.dart:478:28 • deprecated_member_use
info • 'activeColor' is deprecated and shouldn't be used. Use activeThumbColor instead. This feature was deprecated after v3.31.0-2.0.pre • kifi-app/lib/features/auth/presentation/profile_screen.dart:519:9 • deprecated_member_use
info • 'withOpacity' is deprecated and shouldn't be used. Use .withValues() to avoid precision loss • kifi-app/lib/features/auth/presentation/profile_screen.dart:530:45 • deprecated_member_use
info • 'withOpacity' is deprecated and shouldn't be used. Use .withValues() to avoid precision loss • kifi-app/lib/features/auth/presentation/reset_password_screen.dart:143:63 • deprecated_member_use
info • 'withOpacity' is deprecated and shouldn't be used. Use .withValues() to avoid precision loss • kifi-app/lib/features/auth/presentation/setup_wizard_screen.dart:199:63 • deprecated_member_use
info • 'withOpacity' is deprecated and shouldn't be used. Use .withValues() to avoid precision loss • kifi-app/lib/features/auth/presentation/setup_wizard_screen.dart:257:48 • deprecated_member_use
info • 'withOpacity' is deprecated and shouldn't be used. Use .withValues() to avoid precision loss • kifi-app/lib/features/auth/presentation/setup_wizard_screen.dart:270:41 • deprecated_member_use
info • 'value' is deprecated and shouldn't be used. Use initialValue instead. This will set the initial value for the form field. This feature was deprecated after v3.33.0-1.0.pre • kifi-app/lib/features/auth/presentation/setup_wizard_screen.dart:407:11 • deprecated_member_use
info • 'withOpacity' is deprecated and shouldn't be used. Use .withValues() to avoid precision loss • kifi-app/lib/features/auth/presentation/setup_wizard_screen.dart:497:37 • deprecated_member_use
info • Statements in an if should be enclosed in a block • kifi-app/lib/features/auth/presentation/setup_wizard_screen.dart:563:7 • curly_braces_in_flow_control_structures
info • The private field _isSearching could be 'final' • kifi-app/lib/features/budget/presentation/budget_screen.dart:18:8 • prefer_final_fields
warning • The value of the field '_isSearching' isn't used • kifi-app/lib/features/budget/presentation/budget_screen.dart:18:8 • unused_field
info • 'activeColor' is deprecated and shouldn't be used. Use activeThumbColor instead. This feature was deprecated after v3.31.0-2.0.pre • kifi-app/lib/features/budget/presentation/budget_screen.dart:81:25 • deprecated_member_use
info • Don't use 'BuildContext's across async gaps, guarded by an unrelated 'mounted' check • kifi-app/lib/features/budget/presentation/budget_screen.dart:110:60 • use_build_context_synchronously
info • 'value' is deprecated and shouldn't be used. Use initialValue instead. This will set the initial value for the form field. This feature was deprecated after v3.33.0-1.0.pre • kifi-app/lib/features/budget/presentation/budget_screen.dart:168:23 • deprecated_member_use
info • Statements in an if should be enclosed in a block • kifi-app/lib/features/budget/presentation/budget_screen.dart:362:35 • curly_braces_in_flow_control_structures
info • Statements in an if should be enclosed in a block • kifi-app/lib/features/budget/presentation/budget_screen.dart:363:40 • curly_braces_in_flow_control_structures
warning • Unused import: '../../../inventory/presentation/quick_adjust_stock_screen.dart' • kifi-app/lib/features/business/presentation/hub/business_hub_screen.dart:7:8 • unused_import
info • 'withOpacity' is deprecated and shouldn't be used. Use .withValues() to avoid precision loss • kifi-app/lib/features/business/presentation/hub/business_hub_screen.dart:63:64 • deprecated_member_use
info • 'withOpacity' is deprecated and shouldn't be used. Use .withValues() to avoid precision loss • kifi-app/lib/features/business/presentation/hub/business_hub_screen.dart:68:43 • deprecated_member_use
warning • Dead code • kifi-app/lib/features/business/presentation/hub/business_hub_screen.dart:233:48 • dead_code
warning • The left operand can't be null, so the right operand is never executed • kifi-app/lib/features/business/presentation/hub/business_hub_screen.dart:233:51 • dead_null_aware_expression
info • 'withOpacity' is deprecated and shouldn't be used. Use .withValues() to avoid precision loss • kifi-app/lib/features/business/presentation/hub/business_hub_screen.dart:243:48 • deprecated_member_use
info • 'withOpacity' is deprecated and shouldn't be used. Use .withValues() to avoid precision loss • kifi-app/lib/features/business/presentation/hub/business_hub_screen.dart:270:48 • deprecated_member_use
info • 'withOpacity' is deprecated and shouldn't be used. Use .withValues() to avoid precision loss • kifi-app/lib/features/business/presentation/hub/business_hub_screen.dart:271:51 • deprecated_member_use
info • 'withOpacity' is deprecated and shouldn't be used. Use .withValues() to avoid precision loss • kifi-app/lib/features/business/presentation/hub/business_hub_screen.dart:275:50 • deprecated_member_use
info • 'withOpacity' is deprecated and shouldn't be used. Use .withValues() to avoid precision loss • kifi-app/lib/features/business/presentation/hub/business_hub_screen.dart:276:53 • deprecated_member_use
info • 'withOpacity' is deprecated and shouldn't be used. Use .withValues() to avoid precision loss • kifi-app/lib/features/business/presentation/hub/business_hub_screen.dart:285:54 • deprecated_member_use
info • 'withOpacity' is deprecated and shouldn't be used. Use .withValues() to avoid precision loss • kifi-app/lib/features/business/presentation/hub/business_hub_screen.dart:286:57 • deprecated_member_use
info • 'withOpacity' is deprecated and shouldn't be used. Use .withValues() to avoid precision loss • kifi-app/lib/features/business/presentation/hub/business_hub_screen.dart:375:24 • deprecated_member_use
info • 'withOpacity' is deprecated and shouldn't be used. Use .withValues() to avoid precision loss • kifi-app/lib/features/business/presentation/hub/business_hub_screen.dart:377:43 • deprecated_member_use
info • 'withOpacity' is deprecated and shouldn't be used. Use .withValues() to avoid precision loss • kifi-app/lib/features/business/presentation/hub/business_hub_screen.dart:396:45 • deprecated_member_use
info • 'withOpacity' is deprecated and shouldn't be used. Use .withValues() to avoid precision loss • kifi-app/lib/features/business/presentation/reports/reports_screen.dart:82:34 • deprecated_member_use
info • 'value' is deprecated and shouldn't be used. Use initialValue instead. This will set the initial value for the form field. This feature was deprecated after v3.33.0-1.0.pre • kifi-app/lib/features/business/presentation/widgets/business_profile_form_sheet.dart:161:29 • deprecated_member_use
info • The private field _isSearching could be 'final' • kifi-app/lib/features/dashboard/presentation/accounts_screen.dart:21:8 • prefer_final_fields
warning • The value of the field '_isSearching' isn't used • kifi-app/lib/features/dashboard/presentation/accounts_screen.dart:21:8 • unused_field
info • 'value' is deprecated and shouldn't be used. Use initialValue instead. This will set the initial value for the form field. This feature was deprecated after v3.33.0-1.0.pre • kifi-app/lib/features/dashboard/presentation/accounts_screen.dart:118:25 • deprecated_member_use
info • Statements in an if should be enclosed in a block • kifi-app/lib/features/dashboard/presentation/accounts_screen.dart:129:44 • curly_braces_in_flow_control_structures
info • 'value' is deprecated and shouldn't be used. Use initialValue instead. This will set the initial value for the form field. This feature was deprecated after v3.33.0-1.0.pre • kifi-app/lib/features/dashboard/presentation/accounts_screen.dart:148:27 • deprecated_member_use
info • 'value' is deprecated and shouldn't be used. Use initialValue instead. This will set the initial value for the form field. This feature was deprecated after v3.33.0-1.0.pre • kifi-app/lib/features/dashboard/presentation/accounts_screen.dart:205:33 • deprecated_member_use
warning • The value of the local variable 'newWallet' isn't used • kifi-app/lib/features/dashboard/presentation/accounts_screen.dart:312:39 • unused_local_variable
info • 'value' is deprecated and shouldn't be used. Use initialValue instead. This will set the initial value for the form field. This feature was deprecated after v3.33.0-1.0.pre • kifi-app/lib/features/dashboard/presentation/accounts_screen.dart:382:23 • deprecated_member_use
info • 'value' is deprecated and shouldn't be used. Use initialValue instead. This will set the initial value for the form field. This feature was deprecated after v3.33.0-1.0.pre • kifi-app/lib/features/dashboard/presentation/accounts_screen.dart:637:45 • deprecated_member_use
info • Statements in an if should be enclosed in a block • kifi-app/lib/features/dashboard/presentation/accounts_screen.dart:646:64 • curly_braces_in_flow_control_structures
info • 'value' is deprecated and shouldn't be used. Use initialValue instead. This will set the initial value for the form field. This feature was deprecated after v3.33.0-1.0.pre • kifi-app/lib/features/dashboard/presentation/accounts_screen.dart:717:47 • deprecated_member_use
info • 'value' is deprecated and shouldn't be used. Use initialValue instead. This will set the initial value for the form field. This feature was deprecated after v3.33.0-1.0.pre • kifi-app/lib/features/dashboard/presentation/accounts_screen.dart:766:53 • deprecated_member_use
info • Don't invoke 'print' in production code • kifi-app/lib/features/dashboard/presentation/accounts_screen.dart:818:53 • avoid_print
info • Don't invoke 'print' in production code • kifi-app/lib/features/dashboard/presentation/accounts_screen.dart:819:53 • avoid_print
info • Don't invoke 'print' in production code • kifi-app/lib/features/dashboard/presentation/accounts_screen.dart:820:53 • avoid_print
info • Don't invoke 'print' in production code • kifi-app/lib/features/dashboard/presentation/accounts_screen.dart:821:53 • avoid_print
info • The private field _autoCompleteCtrl could be 'final' • kifi-app/lib/features/dashboard/presentation/accounts_screen.dart:955:25 • prefer_final_fields
warning • The receiver can't be null, so the null-aware operator '?.' is unnecessary • kifi-app/lib/features/dashboard/presentation/accounts_screen.dart:1068:38 • invalid_null_aware_operator
warning • The receiver can't be null, so the null-aware operator '?.' is unnecessary • kifi-app/lib/features/dashboard/presentation/accounts_screen.dart:1068:92 • invalid_null_aware_operator
info • 'withOpacity' is deprecated and shouldn't be used. Use .withValues() to avoid precision loss • kifi-app/lib/features/dashboard/presentation/accounts_screen.dart:1082:69 • deprecated_member_use
info • Unnecessary use of multiple underscores • kifi-app/lib/features/dashboard/presentation/accounts_screen.dart:1088:49 • unnecessary_underscores
warning • Unused import: '../../projects/presentation/project_hub_screen.dart' • kifi-app/lib/features/dashboard/presentation/dashboard_screen.dart:3:8 • unused_import
warning • Unused import: '../../projects/presentation/projects_screen.dart' • kifi-app/lib/features/dashboard/presentation/dashboard_screen.dart:4:8 • unused_import
warning • Unused import: '../../sales/domain/invoice.dart' • kifi-app/lib/features/dashboard/presentation/dashboard_screen.dart:21:8 • unused_import
info • Statements in an if should be enclosed in a block • kifi-app/lib/features/dashboard/presentation/dashboard_screen.dart:167:28 • curly_braces_in_flow_control_structures
info • Statements in an if should be enclosed in a block • kifi-app/lib/features/dashboard/presentation/dashboard_screen.dart:177:30 • curly_braces_in_flow_control_structures
info • Statements in an if should be enclosed in a block • kifi-app/lib/features/dashboard/presentation/dashboard_screen.dart:178:35 • curly_braces_in_flow_control_structures
info • Statements in an if should be enclosed in a block • kifi-app/lib/features/dashboard/presentation/dashboard_screen.dart:179:35 • curly_braces_in_flow_control_structures
warning • The value of the local variable 'totalIncome' isn't used • kifi-app/lib/features/dashboard/presentation/dashboard_screen.dart:291:17 • unused_local_variable
warning • The value of the local variable 'totalExpense' isn't used • kifi-app/lib/features/dashboard/presentation/dashboard_screen.dart:292:17 • unused_local_variable
warning • The value of the local variable 'totalInvestment' isn't used • kifi-app/lib/features/dashboard/presentation/dashboard_screen.dart:293:17 • unused_local_variable
warning • The value of the local variable 'totalPayablesPeriod' isn't used • kifi-app/lib/features/dashboard/presentation/dashboard_screen.dart:295:18 • unused_local_variable
warning • The value of the local variable 'totalReceivablesPeriod' isn't used • kifi-app/lib/features/dashboard/presentation/dashboard_screen.dart:296:18 • unused_local_variable
warning • Dead code • kifi-app/lib/features/dashboard/presentation/dashboard_screen.dart:348:52 • dead_code
warning • The left operand can't be null, so the right operand is never executed • kifi-app/lib/features/dashboard/presentation/dashboard_screen.dart:348:55 • dead_null_aware_expression
info • 'withOpacity' is deprecated and shouldn't be used. Use .withValues() to avoid precision loss • kifi-app/lib/features/dashboard/presentation/dashboard_screen.dart:590:64 • deprecated_member_use
warning • The value of the local variable 'safeIndex' isn't used • kifi-app/lib/features/dashboard/presentation/dashboard_screen.dart:666:15 • unused_local_variable
info • 'withOpacity' is deprecated and shouldn't be used. Use .withValues() to avoid precision loss • kifi-app/lib/features/dashboard/presentation/dashboard_screen.dart:705:24 • deprecated_member_use
info • 'withOpacity' is deprecated and shouldn't be used. Use .withValues() to avoid precision loss • kifi-app/lib/features/dashboard/presentation/dashboard_screen.dart:707:43 • deprecated_member_use
info • 'value' is deprecated and shouldn't be used. Use initialValue instead. This will set the initial value for the form field. This feature was deprecated after v3.33.0-1.0.pre • kifi-app/lib/features/dashboard/presentation/maturity_dialog.dart:222:17 • deprecated_member_use
info • Don't use 'BuildContext's across async gaps, guarded by an unrelated 'mounted' check • kifi-app/lib/features/dashboard/presentation/maturity_dialog.dart:274:43 • use_build_context_synchronously
info • Don't use 'BuildContext's across async gaps, guarded by an unrelated 'mounted' check • kifi-app/lib/features/dashboard/presentation/maturity_dialog.dart:275:50 • use_build_context_synchronously
info • Don't use 'BuildContext's across async gaps, guarded by an unrelated 'mounted' check • kifi-app/lib/features/dashboard/presentation/maturity_dialog.dart:283:50 • use_build_context_synchronously
warning • Unused import: '../../../core/theme/nature_colors.dart' • kifi-app/lib/features/dashboard/presentation/wallet_ledger_screen.dart:6:8 • unused_import
info • Statements in an if should be enclosed in a block • kifi-app/lib/features/dashboard/presentation/widgets/budget_status_card.dart:47:7 • curly_braces_in_flow_control_structures
info • Statements in an if should be enclosed in a block • kifi-app/lib/features/dashboard/presentation/widgets/budget_status_card.dart:49:7 • curly_braces_in_flow_control_structures
info • Statements in an if should be enclosed in a block • kifi-app/lib/features/dashboard/presentation/widgets/category_spending_chart.dart:32:9 • curly_braces_in_flow_control_structures
info • Statements in an if should be enclosed in a block • kifi-app/lib/features/dashboard/presentation/widgets/category_spending_chart.dart:36:9 • curly_braces_in_flow_control_structures
info • Statements in an if should be enclosed in a block • kifi-app/lib/features/dashboard/presentation/widgets/category_spending_chart.dart:40:9 • curly_braces_in_flow_control_structures
info • 'withOpacity' is deprecated and shouldn't be used. Use .withValues() to avoid precision loss • kifi-app/lib/features/dashboard/presentation/widgets/category_spending_chart.dart:114:49 • deprecated_member_use
info • 'withOpacity' is deprecated and shouldn't be used. Use .withValues() to avoid precision loss • kifi-app/lib/features/dashboard/presentation/widgets/category_spending_chart.dart:126:49 • deprecated_member_use
info • 'withOpacity' is deprecated and shouldn't be used. Use .withValues() to avoid precision loss • kifi-app/lib/features/dashboard/presentation/widgets/category_spending_chart.dart:246:42 • deprecated_member_use
info • Statements in an if should be enclosed in a block • kifi-app/lib/features/dashboard/presentation/widgets/day_wise_spending_chart.dart:49:11 • curly_braces_in_flow_control_structures
info • Statements in an if should be enclosed in a block • kifi-app/lib/features/dashboard/presentation/widgets/day_wise_spending_chart.dart:53:11 • curly_braces_in_flow_control_structures
info • Statements in an if should be enclosed in a block • kifi-app/lib/features/dashboard/presentation/widgets/day_wise_spending_chart.dart:57:11 • curly_braces_in_flow_control_structures
info • Statements in an if should be enclosed in a block • kifi-app/lib/features/dashboard/presentation/widgets/day_wise_spending_chart.dart:66:17 • curly_braces_in_flow_control_structures
info • Statements in an if should be enclosed in a block • kifi-app/lib/features/dashboard/presentation/widgets/day_wise_spending_chart.dart:69:17 • curly_braces_in_flow_control_structures
info • Statements in an if should be enclosed in a block • kifi-app/lib/features/dashboard/presentation/widgets/day_wise_spending_chart.dart:130:31 • curly_braces_in_flow_control_structures
info • Statements in an if should be enclosed in a block • kifi-app/lib/features/dashboard/presentation/widgets/day_wise_spending_chart.dart:136:31 • curly_braces_in_flow_control_structures
info • Statements in an if should be enclosed in a block • kifi-app/lib/features/dashboard/presentation/widgets/day_wise_spending_chart.dart:138:31 • curly_braces_in_flow_control_structures
info • 'withOpacity' is deprecated and shouldn't be used. Use .withValues() to avoid precision loss • kifi-app/lib/features/dashboard/presentation/widgets/statistics_tab.dart:53:49 • deprecated_member_use
info • 'withOpacity' is deprecated and shouldn't be used. Use .withValues() to avoid precision loss • kifi-app/lib/features/dashboard/presentation/widgets/statistics_tab.dart:65:42 • deprecated_member_use
info • 'withOpacity' is deprecated and shouldn't be used. Use .withValues() to avoid precision loss • kifi-app/lib/features/dashboard/presentation/widgets/statistics_tab.dart:207:43 • deprecated_member_use
info • 'withOpacity' is deprecated and shouldn't be used. Use .withValues() to avoid precision loss • kifi-app/lib/features/dashboard/presentation/widgets/statistics_tab.dart:257:65 • deprecated_member_use
warning • Unused import: 'package:lucide_icons/lucide_icons.dart' • kifi-app/lib/features/dashboard/presentation/widgets/swipeable_account_card.dart:2:8 • unused_import
info • 'withOpacity' is deprecated and shouldn't be used. Use .withValues() to avoid precision loss • kifi-app/lib/features/dashboard/presentation/widgets/swipeable_account_card.dart:82:38 • deprecated_member_use
info • 'withOpacity' is deprecated and shouldn't be used. Use .withValues() to avoid precision loss • kifi-app/lib/features/dashboard/presentation/widgets/swipeable_account_card.dart:86:45 • deprecated_member_use
info • 'withOpacity' is deprecated and shouldn't be used. Use .withValues() to avoid precision loss • kifi-app/lib/features/dashboard/presentation/widgets/swipeable_account_card.dart:97:45 • deprecated_member_use
info • 'withOpacity' is deprecated and shouldn't be used. Use .withValues() to avoid precision loss • kifi-app/lib/features/dashboard/presentation/widgets/swipeable_account_card.dart:161:37 • deprecated_member_use
info • 'withOpacity' is deprecated and shouldn't be used. Use .withValues() to avoid precision loss • kifi-app/lib/features/dashboard/presentation/widgets/upcoming_dues_widget.dart:142:42 • deprecated_member_use
info • 'withOpacity' is deprecated and shouldn't be used. Use .withValues() to avoid precision loss • kifi-app/lib/features/dashboard/presentation/widgets/upcoming_dues_widget.dart:148:40 • deprecated_member_use
info • 'withOpacity' is deprecated and shouldn't be used. Use .withValues() to avoid precision loss • kifi-app/lib/features/dashboard/presentation/widgets/upcoming_dues_widget.dart:152:38 • deprecated_member_use
info • 'withOpacity' is deprecated and shouldn't be used. Use .withValues() to avoid precision loss • kifi-app/lib/features/dashboard/presentation/widgets/upcoming_dues_widget.dart:157:41 • deprecated_member_use
info • 'withOpacity' is deprecated and shouldn't be used. Use .withValues() to avoid precision loss • kifi-app/lib/features/dashboard/presentation/widgets/upcoming_dues_widget.dart:172:30 • deprecated_member_use
info • The import of 'package:flutter_image_compress/flutter_image_compress.dart' is unnecessary because all of the used elements are also provided by the import of 'package:image_picker/image_picker.dart' • kifi-app/lib/features/inventory/presentation/add_product_screen.dart:6:8 • unnecessary_import
info • 'withOpacity' is deprecated and shouldn't be used. Use .withValues() to avoid precision loss • kifi-app/lib/features/inventory/presentation/add_product_screen.dart:273:87 • deprecated_member_use
info • 'withOpacity' is deprecated and shouldn't be used. Use .withValues() to avoid precision loss • kifi-app/lib/features/inventory/presentation/add_product_screen.dart:310:70 • deprecated_member_use
info • 'withOpacity' is deprecated and shouldn't be used. Use .withValues() to avoid precision loss • kifi-app/lib/features/inventory/presentation/add_product_screen.dart:369:70 • deprecated_member_use
info • 'value' is deprecated and shouldn't be used. Use initialValue instead. This will set the initial value for the form field. This feature was deprecated after v3.33.0-1.0.pre • kifi-app/lib/features/inventory/presentation/add_product_screen.dart:422:13 • deprecated_member_use
warning • Dead code • kifi-app/lib/features/inventory/presentation/add_product_screen.dart:490:28 • dead_code
info • 'withOpacity' is deprecated and shouldn't be used. Use .withValues() to avoid precision loss • kifi-app/lib/features/inventory/presentation/add_product_screen.dart:496:58 • deprecated_member_use
info • 'activeColor' is deprecated and shouldn't be used. Use activeThumbColor instead. This feature was deprecated after v3.31.0-2.0.pre • kifi-app/lib/features/inventory/presentation/add_product_screen.dart:509:25 • deprecated_member_use
info • 'surfaceVariant' is deprecated and shouldn't be used. Use surfaceContainerHighest instead. This feature was deprecated after v3.18.0-0.1.pre • kifi-app/lib/features/inventory/presentation/add_product_screen.dart:623:52 • deprecated_member_use
info • 'withOpacity' is deprecated and shouldn't be used. Use .withValues() to avoid precision loss • kifi-app/lib/features/inventory/presentation/add_product_screen.dart:623:67 • deprecated_member_use
info • Don't use 'BuildContext's across async gaps, guarded by an unrelated 'mounted' check • kifi-app/lib/features/inventory/presentation/add_product_screen.dart:676:59 • use_build_context_synchronously
info • 'withOpacity' is deprecated and shouldn't be used. Use .withValues() to avoid precision loss • kifi-app/lib/features/inventory/presentation/add_product_screen.dart:701:64 • deprecated_member_use
info • 'withOpacity' is deprecated and shouldn't be used. Use .withValues() to avoid precision loss • kifi-app/lib/features/inventory/presentation/add_product_screen.dart:702:83 • deprecated_member_use
info • 'withOpacity' is deprecated and shouldn't be used. Use .withValues() to avoid precision loss • kifi-app/lib/features/inventory/presentation/add_product_screen.dart:729:53 • deprecated_member_use
info • 'withOpacity' is deprecated and shouldn't be used. Use .withValues() to avoid precision loss • kifi-app/lib/features/inventory/presentation/add_product_screen.dart:730:57 • deprecated_member_use
info • 'withOpacity' is deprecated and shouldn't be used. Use .withValues() to avoid precision loss • kifi-app/lib/features/inventory/presentation/add_product_screen.dart:759:61 • deprecated_member_use
warning • Unused import: '../../../core/theme/nature_colors.dart' • kifi-app/lib/features/inventory/presentation/category_management_screen.dart:4:8 • unused_import
info • 'withOpacity' is deprecated and shouldn't be used. Use .withValues() to avoid precision loss • kifi-app/lib/features/inventory/presentation/category_management_screen.dart:88:63 • deprecated_member_use
info • 'withOpacity' is deprecated and shouldn't be used. Use .withValues() to avoid precision loss • kifi-app/lib/features/inventory/presentation/category_management_screen.dart:110:50 • deprecated_member_use
info • 'withOpacity' is deprecated and shouldn't be used. Use .withValues() to avoid precision loss • kifi-app/lib/features/inventory/presentation/category_management_screen.dart:113:45 • deprecated_member_use
info • 'withOpacity' is deprecated and shouldn't be used. Use .withValues() to avoid precision loss • kifi-app/lib/features/inventory/presentation/category_management_screen.dart:113:77 • deprecated_member_use
info • 'withOpacity' is deprecated and shouldn't be used. Use .withValues() to avoid precision loss • kifi-app/lib/features/inventory/presentation/category_management_screen.dart:118:39 • deprecated_member_use
info • 'withOpacity' is deprecated and shouldn't be used. Use .withValues() to avoid precision loss • kifi-app/lib/features/inventory/presentation/category_management_screen.dart:132:46 • deprecated_member_use
info • 'withOpacity' is deprecated and shouldn't be used. Use .withValues() to avoid precision loss • kifi-app/lib/features/inventory/presentation/category_management_screen.dart:164:56 • deprecated_member_use
warning • Dead code • kifi-app/lib/features/inventory/presentation/category_management_screen.dart:282:50 • dead_code
warning • The left operand can't be null, so the right operand is never executed • kifi-app/lib/features/inventory/presentation/category_management_screen.dart:282:53 • dead_null_aware_expression
warning • The left operand can't be null, so the right operand is never executed • kifi-app/lib/features/inventory/presentation/category_management_screen.dart:284:35 • dead_null_aware_expression
info • 'withOpacity' is deprecated and shouldn't be used. Use .withValues() to avoid precision loss • kifi-app/lib/features/inventory/presentation/category_management_screen.dart:338:41 • deprecated_member_use
info • 'withOpacity' is deprecated and shouldn't be used. Use .withValues() to avoid precision loss • kifi-app/lib/features/inventory/presentation/category_management_screen.dart:350:36 • deprecated_member_use
info • 'value' is deprecated and shouldn't be used. Use initialValue instead. This will set the initial value for the form field. This feature was deprecated after v3.33.0-1.0.pre • kifi-app/lib/features/inventory/presentation/category_management_screen.dart:391:25 • deprecated_member_use
info • 'withOpacity' is deprecated and shouldn't be used. Use .withValues() to avoid precision loss • kifi-app/lib/features/inventory/presentation/category_management_screen.dart:423:61 • deprecated_member_use
info • 'withOpacity' is deprecated and shouldn't be used. Use .withValues() to avoid precision loss • kifi-app/lib/features/inventory/presentation/category_management_screen.dart:430:58 • deprecated_member_use
info • 'withOpacity' is deprecated and shouldn't be used. Use .withValues() to avoid precision loss • kifi-app/lib/features/inventory/presentation/category_management_screen.dart:430:99 • deprecated_member_use
info • 'activeColor' is deprecated and shouldn't be used. Use activeThumbColor instead. This feature was deprecated after v3.31.0-2.0.pre • kifi-app/lib/features/inventory/presentation/category_management_screen.dart:451:27 • deprecated_member_use
info • 'value' is deprecated and shouldn't be used. Use initialValue instead. This will set the initial value for the form field. This feature was deprecated after v3.33.0-1.0.pre • kifi-app/lib/features/inventory/presentation/category_management_screen.dart:464:25 • deprecated_member_use
info • 'value' is deprecated and shouldn't be used. Use initialValue instead. This will set the initial value for the form field. This feature was deprecated after v3.33.0-1.0.pre • kifi-app/lib/features/inventory/presentation/category_management_screen.dart:513:29 • deprecated_member_use
info • 'value' is deprecated and shouldn't be used. Use initialValue instead. This will set the initial value for the form field. This feature was deprecated after v3.33.0-1.0.pre • kifi-app/lib/features/inventory/presentation/category_management_screen.dart:540:29 • deprecated_member_use
info • 'value' is deprecated and shouldn't be used. Use initialValue instead. This will set the initial value for the form field. This feature was deprecated after v3.33.0-1.0.pre • kifi-app/lib/features/inventory/presentation/category_management_screen.dart:554:29 • deprecated_member_use
info • 'withOpacity' is deprecated and shouldn't be used. Use .withValues() to avoid precision loss • kifi-app/lib/features/inventory/presentation/category_management_screen.dart:587:54 • deprecated_member_use
info • 'withOpacity' is deprecated and shouldn't be used. Use .withValues() to avoid precision loss • kifi-app/lib/features/inventory/presentation/daily_rates_screen.dart:167:50 • deprecated_member_use
info • Unnecessary use of multiple underscores • kifi-app/lib/features/inventory/presentation/daily_rates_screen.dart:299:55 • unnecessary_underscores
warning • Unused import: 'package:kifi_app/features/inventory/presentation/widgets/adjust_stock_sheet.dart' • kifi-app/lib/features/inventory/presentation/product_detail_screen.dart:8:8 • unused_import
info • 'withOpacity' is deprecated and shouldn't be used. Use .withValues() to avoid precision loss • kifi-app/lib/features/inventory/presentation/product_list_screen.dart:157:50 • deprecated_member_use
info • 'withOpacity' is deprecated and shouldn't be used. Use .withValues() to avoid precision loss • kifi-app/lib/features/inventory/presentation/product_list_screen.dart:207:68 • deprecated_member_use
info • Missing type annotation • kifi-app/lib/features/inventory/presentation/product_list_screen.dart:302:29 • strict_top_level_inference
info • 'withOpacity' is deprecated and shouldn't be used. Use .withValues() to avoid precision loss • kifi-app/lib/features/inventory/presentation/product_list_screen.dart:308:30 • deprecated_member_use
info • Missing type annotation • kifi-app/lib/features/inventory/presentation/quick_adjust_stock_screen.dart:175:29 • strict_top_level_inference
info • 'withOpacity' is deprecated and shouldn't be used. Use .withValues() to avoid precision loss • kifi-app/lib/features/inventory/presentation/quick_adjust_stock_screen.dart:181:30 • deprecated_member_use
info • 'withOpacity' is deprecated and shouldn't be used. Use .withValues() to avoid precision loss • kifi-app/lib/features/inventory/presentation/stock_ledger_tab.dart:87:38 • deprecated_member_use
info • 'withOpacity' is deprecated and shouldn't be used. Use .withValues() to avoid precision loss • kifi-app/lib/features/inventory/presentation/stock_ledger_tab.dart:88:36 • deprecated_member_use
info • 'value' is deprecated and shouldn't be used. Use initialValue instead. This will set the initial value for the form field. This feature was deprecated after v3.33.0-1.0.pre • kifi-app/lib/features/inventory/presentation/widgets/adjust_stock_sheet.dart:100:13 • deprecated_member_use
warning • Unused import: '../../../../core/theme/nature_colors.dart' • kifi-app/lib/features/inventory/presentation/widgets/quick_rate_update_sheet.dart:3:8 • unused_import
info • 'withOpacity' is deprecated and shouldn't be used. Use .withValues() to avoid precision loss • kifi-app/lib/features/inventory/presentation/widgets/quick_rate_update_sheet.dart:79:36 • deprecated_member_use
info • 'withOpacity' is deprecated and shouldn't be used. Use .withValues() to avoid precision loss • kifi-app/lib/features/inventory/presentation/widgets/quick_rate_update_sheet.dart:90:40 • deprecated_member_use
info • 'withOpacity' is deprecated and shouldn't be used. Use .withValues() to avoid precision loss • kifi-app/lib/features/inventory/presentation/widgets/quick_rate_update_sheet.dart:112:36 • deprecated_member_use
info • 'withOpacity' is deprecated and shouldn't be used. Use .withValues() to avoid precision loss • kifi-app/lib/features/inventory/presentation/widgets/quick_rate_update_sheet.dart:114:55 • deprecated_member_use
info • 'value' is deprecated and shouldn't be used. Use initialValue instead. This will set the initial value for the form field. This feature was deprecated after v3.33.0-1.0.pre • kifi-app/lib/features/inventory/presentation/widgets/quick_rate_update_sheet.dart:126:15 • deprecated_member_use
info • Don't invoke 'print' in production code • kifi-app/lib/features/inventory/providers/product_categories_provider.dart:128:7 • avoid_print
info • Don't invoke 'print' in production code • kifi-app/lib/features/inventory/providers/product_categories_provider.dart:160:9 • avoid_print
info • The import of 'package:image_picker/image_picker.dart' is unnecessary because all of the used elements are also provided by the import of 'package:flutter_image_compress/flutter_image_compress.dart' • kifi-app/lib/features/inventory/providers/products_provider.dart:10:8 • unnecessary_import
warning • The stack trace variable 'stack' isn't used and can be removed • kifi-app/lib/features/inventory/providers/products_provider.dart:69:17 • unused_catch_stack
info • Use the null-aware marker '?' rather than a null check via an 'if' • kifi-app/lib/features/projects/data/project_repository.dart:37:9 • use_null_aware_elements
info • Use the null-aware marker '?' rather than a null check via an 'if' • kifi-app/lib/features/projects/data/project_repository.dart:38:9 • use_null_aware_elements
info • Use the null-aware marker '?' rather than a null check via an 'if' • kifi-app/lib/features/projects/data/project_repository.dart:39:9 • use_null_aware_elements
info • Use the null-aware marker '?' rather than a null check via an 'if' • kifi-app/lib/features/projects/data/project_repository.dart:56:9 • use_null_aware_elements
info • Use the null-aware marker '?' rather than a null check via an 'if' • kifi-app/lib/features/projects/data/project_repository.dart:57:9 • use_null_aware_elements
info • Use the null-aware marker '?' rather than a null check via an 'if' • kifi-app/lib/features/projects/data/project_repository.dart:58:9 • use_null_aware_elements
info • Use the null-aware marker '?' rather than a null check via an 'if' • kifi-app/lib/features/projects/data/project_repository.dart:59:9 • use_null_aware_elements
info • Use the null-aware marker '?' rather than a null check via an 'if' • kifi-app/lib/features/projects/data/project_repository.dart:60:9 • use_null_aware_elements
info • Use the null-aware marker '?' rather than a null check via an 'if' • kifi-app/lib/features/projects/data/project_repository.dart:88:9 • use_null_aware_elements
info • Use the null-aware marker '?' rather than a null check via an 'if' • kifi-app/lib/features/projects/data/project_repository.dart:89:9 • use_null_aware_elements
info • Use the null-aware marker '?' rather than a null check via an 'if' • kifi-app/lib/features/projects/data/project_repository.dart:90:9 • use_null_aware_elements
info • Use the null-aware marker '?' rather than a null check via an 'if' • kifi-app/lib/features/projects/data/project_repository.dart:91:9 • use_null_aware_elements
info • Use the null-aware marker '?' rather than a null check via an 'if' • kifi-app/lib/features/projects/data/project_repository.dart:92:9 • use_null_aware_elements
info • Use the null-aware marker '?' rather than a null check via an 'if' • kifi-app/lib/features/projects/data/project_repository.dart:112:9 • use_null_aware_elements
info • Use the null-aware marker '?' rather than a null check via an 'if' • kifi-app/lib/features/projects/data/project_repository.dart:113:9 • use_null_aware_elements
info • Use the null-aware marker '?' rather than a null check via an 'if' • kifi-app/lib/features/projects/data/project_repository.dart:114:9 • use_null_aware_elements
info • Use the null-aware marker '?' rather than a null check via an 'if' • kifi-app/lib/features/projects/data/project_repository.dart:115:9 • use_null_aware_elements
info • Use the null-aware marker '?' rather than a null check via an 'if' • kifi-app/lib/features/projects/data/project_repository.dart:116:9 • use_null_aware_elements
info • Use the null-aware marker '?' rather than a null check via an 'if' • kifi-app/lib/features/projects/data/project_repository.dart:117:9 • use_null_aware_elements
info • Use the null-aware marker '?' rather than a null check via an 'if' • kifi-app/lib/features/projects/data/project_repository.dart:118:9 • use_null_aware_elements
info • Use the null-aware marker '?' rather than a null check via an 'if' • kifi-app/lib/features/projects/data/project_repository.dart:119:9 • use_null_aware_elements
warning • Dead code • kifi-app/lib/features/projects/presentation/widgets/add_project_sheet.dart:32:40 • dead_code
warning • The left operand can't be null, so the right operand is never executed • kifi-app/lib/features/projects/presentation/widgets/add_project_sheet.dart:32:43 • dead_null_aware_expression
info • 'value' is deprecated and shouldn't be used. Use initialValue instead. This will set the initial value for the form field. This feature was deprecated after v3.33.0-1.0.pre • kifi-app/lib/features/projects/presentation/widgets/add_project_sheet.dart:90:27 • deprecated_member_use
info • 'withOpacity' is deprecated and shouldn't be used. Use .withValues() to avoid precision loss • kifi-app/lib/features/projects/presentation/widgets/add_project_sheet.dart:117:72 • deprecated_member_use
info • Don't use 'BuildContext's across async gaps • kifi-app/lib/features/projects/presentation/widgets/add_project_sheet.dart:189:28 • use_build_context_synchronously
info • Statements in an if should be enclosed in a block • kifi-app/lib/features/projects/presentation/widgets/add_task_sheet.dart:171:31 • curly_braces_in_flow_control_structures
info • Parameter 'key' could be a super parameter • kifi-app/lib/features/projects/presentation/widgets/task_details_sheet.dart:18:9 • use_super_parameters
info • Statements in an if should be enclosed in a block • kifi-app/lib/features/projects/presentation/widgets/task_details_sheet.dart:67:11 • curly_braces_in_flow_control_structures
info • Statements in an if should be enclosed in a block • kifi-app/lib/features/projects/presentation/widgets/task_details_sheet.dart:69:11 • curly_braces_in_flow_control_structures
info • Statements in an if should be enclosed in a block • kifi-app/lib/features/projects/presentation/widgets/task_details_sheet.dart:71:11 • curly_braces_in_flow_control_structures
info • 'Share' is deprecated and shouldn't be used. Use SharePlus instead • kifi-app/lib/features/projects/presentation/widgets/task_details_sheet.dart:141:15 • deprecated_member_use
info • 'shareXFiles' is deprecated and shouldn't be used. Use SharePlus.instance.share() instead • kifi-app/lib/features/projects/presentation/widgets/task_details_sheet.dart:141:21 • deprecated_member_use
info • Statements in an if should be enclosed in a block • kifi-app/lib/features/projects/presentation/widgets/task_details_sheet.dart:175:19 • curly_braces_in_flow_control_structures
info • Statements in an if should be enclosed in a block • kifi-app/lib/features/projects/presentation/widgets/task_details_sheet.dart:250:49 • curly_braces_in_flow_control_structures
info • Statements in an if should be enclosed in a block • kifi-app/lib/features/projects/presentation/widgets/task_details_sheet.dart:264:49 • curly_braces_in_flow_control_structures
info • Statements in an if should be enclosed in a block • kifi-app/lib/features/projects/presentation/widgets/task_details_sheet.dart:270:49 • curly_braces_in_flow_control_structures
warning • Unused import: '../../auth/providers/auth_provider.dart' • kifi-app/lib/features/projects/providers/project_provider.dart:3:8 • unused_import
warning • Unused import: 'dart:async' • kifi-app/lib/features/projects/providers/user_provider.dart:4:8 • unused_import
info • Statements in an if should be enclosed in a block • kifi-app/lib/features/sales/domain/invoice.dart:198:7 • curly_braces_in_flow_control_structures
info • Statements in an if should be enclosed in a block • kifi-app/lib/features/sales/domain/invoice.dart:205:7 • curly_braces_in_flow_control_structures
info • Statements in an if should be enclosed in a block • kifi-app/lib/features/sales/domain/invoice.dart:216:7 • curly_braces_in_flow_control_structures
info • Statements in an if should be enclosed in a block • kifi-app/lib/features/sales/domain/invoice.dart:219:7 • curly_braces_in_flow_control_structures
info • Statements in an if should be enclosed in a block • kifi-app/lib/features/sales/domain/invoice.dart:263:7 • curly_braces_in_flow_control_structures
info • Statements in an if should be enclosed in a block • kifi-app/lib/features/sales/domain/invoice.dart:266:7 • curly_braces_in_flow_control_structures
info • 'withOpacity' is deprecated and shouldn't be used. Use .withValues() to avoid precision loss • kifi-app/lib/features/sales/presentation/customer_ledger_screen.dart:183:36 • deprecated_member_use
info • 'withOpacity' is deprecated and shouldn't be used. Use .withValues() to avoid precision loss • kifi-app/lib/features/sales/presentation/customers_list_screen.dart:146:54 • deprecated_member_use
warning • Unused import: '../../inventory/domain/inventory_item.dart' • kifi-app/lib/features/sales/presentation/invoice_builder_screen.dart:17:8 • unused_import
warning • The '!' will have no effect because the receiver can't be null • kifi-app/lib/features/sales/presentation/invoice_builder_screen.dart:205:65 • unnecessary_non_null_assertion
warning • The '!' will have no effect because the receiver can't be null • kifi-app/lib/features/sales/presentation/invoice_builder_screen.dart:206:63 • unnecessary_non_null_assertion
warning • The '!' will have no effect because the receiver can't be null • kifi-app/lib/features/sales/presentation/invoice_builder_screen.dart:207:66 • unnecessary_non_null_assertion
info • Don't use 'BuildContext's across async gaps, guarded by an unrelated 'mounted' check • kifi-app/lib/features/sales/presentation/invoice_builder_screen.dart:395:32 • use_build_context_synchronously
info • Don't use 'BuildContext's across async gaps, guarded by an unrelated 'mounted' check • kifi-app/lib/features/sales/presentation/invoice_builder_screen.dart:399:32 • use_build_context_synchronously
info • 'activeColor' is deprecated and shouldn't be used. Use activeThumbColor instead. This feature was deprecated after v3.31.0-2.0.pre • kifi-app/lib/features/sales/presentation/invoice_builder_screen.dart:539:43 • deprecated_member_use
info • 'withOpacity' is deprecated and shouldn't be used. Use .withValues() to avoid precision loss • kifi-app/lib/features/sales/presentation/invoice_details_screen.dart:115:44 • deprecated_member_use
info • 'withOpacity' is deprecated and shouldn't be used. Use .withValues() to avoid precision loss • kifi-app/lib/features/sales/presentation/invoice_details_screen.dart:144:51 • deprecated_member_use
warning • Dead code • kifi-app/lib/features/sales/presentation/invoice_details_screen.dart:413:41 • dead_code
warning • The left operand can't be null, so the right operand is never executed • kifi-app/lib/features/sales/presentation/invoice_details_screen.dart:413:44 • dead_null_aware_expression
info • 'withOpacity' is deprecated and shouldn't be used. Use .withValues() to avoid precision loss • kifi-app/lib/features/sales/presentation/invoice_details_screen.dart:431:46 • deprecated_member_use
info • 'withOpacity' is deprecated and shouldn't be used. Use .withValues() to avoid precision loss • kifi-app/lib/features/sales/presentation/invoice_details_screen.dart:661:44 • deprecated_member_use
info • Statements in an if should be enclosed in a block • kifi-app/lib/features/sales/presentation/invoice_details_screen.dart:747:23 • curly_braces_in_flow_control_structures
info • 'withOpacity' is deprecated and shouldn't be used. Use .withValues() to avoid precision loss • kifi-app/lib/features/sales/presentation/invoice_details_screen.dart:752:52 • deprecated_member_use
info • 'Share' is deprecated and shouldn't be used. Use SharePlus instead • kifi-app/lib/features/sales/presentation/invoice_details_screen.dart:940:13 • deprecated_member_use
info • 'shareXFiles' is deprecated and shouldn't be used. Use SharePlus.instance.share() instead • kifi-app/lib/features/sales/presentation/invoice_details_screen.dart:940:19 • deprecated_member_use
info • Statements in an if should be enclosed in a block • kifi-app/lib/features/sales/presentation/invoice_details_screen.dart:945:9 • curly_braces_in_flow_control_structures
warning • Dead code • kifi-app/lib/features/sales/presentation/invoice_details_screen.dart:1152:43 • dead_code
warning • The left operand can't be null, so the right operand is never executed • kifi-app/lib/features/sales/presentation/invoice_details_screen.dart:1152:46 • dead_null_aware_expression
info • Statements in an if should be enclosed in a block • kifi-app/lib/features/sales/presentation/invoice_details_screen.dart:1164:23 • curly_braces_in_flow_control_structures
info • Statements in an if should be enclosed in a block • kifi-app/lib/features/sales/presentation/invoice_details_screen.dart:1166:23 • curly_braces_in_flow_control_structures
info • Statements in an if should be enclosed in a block • kifi-app/lib/features/sales/presentation/invoice_details_screen.dart:1168:23 • curly_braces_in_flow_control_structures
info • Statements in an if should be enclosed in a block • kifi-app/lib/features/sales/presentation/invoice_details_screen.dart:1171:23 • curly_braces_in_flow_control_structures
info • Statements in an if should be enclosed in a block • kifi-app/lib/features/sales/presentation/invoice_details_screen.dart:1174:23 • curly_braces_in_flow_control_structures
info • 'Share' is deprecated and shouldn't be used. Use SharePlus instead • kifi-app/lib/features/sales/presentation/invoice_details_screen.dart:1387:13 • deprecated_member_use
info • 'shareXFiles' is deprecated and shouldn't be used. Use SharePlus.instance.share() instead • kifi-app/lib/features/sales/presentation/invoice_details_screen.dart:1387:19 • deprecated_member_use
info • Statements in an if should be enclosed in a block • kifi-app/lib/features/sales/presentation/invoice_details_screen.dart:1392:9 • curly_braces_in_flow_control_structures
warning • Dead code • kifi-app/lib/features/sales/presentation/invoices_list_screen.dart:151:59 • dead_code
warning • The left operand can't be null, so the right operand is never executed • kifi-app/lib/features/sales/presentation/invoices_list_screen.dart:151:62 • dead_null_aware_expression
info • 'withOpacity' is deprecated and shouldn't be used. Use .withValues() to avoid precision loss • kifi-app/lib/features/sales/presentation/invoices_list_screen.dart:333:50 • deprecated_member_use
info • 'withOpacity' is deprecated and shouldn't be used. Use .withValues() to avoid precision loss • kifi-app/lib/features/sales/presentation/invoices_list_screen.dart:392:45 • deprecated_member_use
info • 'withOpacity' is deprecated and shouldn't be used. Use .withValues() to avoid precision loss • kifi-app/lib/features/sales/presentation/invoices_list_screen.dart:485:62 • deprecated_member_use
info • 'withOpacity' is deprecated and shouldn't be used. Use .withValues() to avoid precision loss • kifi-app/lib/features/sales/presentation/invoices_list_screen.dart:488:64 • deprecated_member_use
info • Don't use 'BuildContext's across async gaps, guarded by an unrelated 'mounted' check • kifi-app/lib/features/sales/presentation/widgets/receive_payment_sheet.dart:173:29 • use_build_context_synchronously
info • Don't use 'BuildContext's across async gaps, guarded by an unrelated 'mounted' check • kifi-app/lib/features/sales/presentation/widgets/receive_payment_sheet.dart:176:48 • use_build_context_synchronously
info • Don't use 'BuildContext's across async gaps, guarded by an unrelated 'mounted' check • kifi-app/lib/features/sales/presentation/widgets/receive_payment_sheet.dart:185:29 • use_build_context_synchronously
warning • Unused import: 'dart:io' • kifi-app/lib/features/sales/providers/customers_provider.dart:2:8 • unused_import
info • The import of 'package:image_picker/image_picker.dart' is unnecessary because all of the used elements are also provided by the import of 'package:flutter_image_compress/flutter_image_compress.dart' • kifi-app/lib/features/sales/providers/customers_provider.dart:5:8 • unnecessary_import
info • Don't invoke 'print' in production code • kifi-app/lib/features/sales/providers/customers_provider.dart:30:7 • avoid_print
info • Don't invoke 'print' in production code • kifi-app/lib/features/sales/providers/invoices_provider.dart:22:7 • avoid_print
info • Don't invoke 'print' in production code • kifi-app/lib/features/sales/providers/invoices_provider.dart:88:7 • avoid_print
info • Use the null-aware marker '?' rather than a null check via an 'if' • kifi-app/lib/features/transactions/data/repository.dart:35:7 • use_null_aware_elements
info • Use the null-aware marker '?' rather than a null check via an 'if' • kifi-app/lib/features/transactions/data/repository.dart:36:7 • use_null_aware_elements
info • Use the null-aware marker '?' rather than a null check via an 'if' • kifi-app/lib/features/transactions/data/repository.dart:37:7 • use_null_aware_elements
info • Use the null-aware marker '?' rather than a null check via an 'if' • kifi-app/lib/features/transactions/data/repository.dart:38:7 • use_null_aware_elements
info • Use the null-aware marker '?' rather than a null check via an 'if' • kifi-app/lib/features/transactions/data/repository.dart:39:7 • use_null_aware_elements
info • Don't invoke 'print' in production code • kifi-app/lib/features/transactions/data/repository.dart:106:7 • avoid_print
info • Use the null-aware marker '?' rather than a null check via an 'if' • kifi-app/lib/features/transactions/data/repository.dart:164:7 • use_null_aware_elements
info • Use the null-aware marker '?' rather than a null check via an 'if' • kifi-app/lib/features/transactions/data/repository.dart:168:7 • use_null_aware_elements
info • Use the null-aware marker '?' rather than a null check via an 'if' • kifi-app/lib/features/transactions/data/repository.dart:169:7 • use_null_aware_elements
info • Use the null-aware marker '?' rather than a null check via an 'if' • kifi-app/lib/features/transactions/data/repository.dart:170:7 • use_null_aware_elements
info • Use the null-aware marker '?' rather than a null check via an 'if' • kifi-app/lib/features/transactions/data/repository.dart:171:7 • use_null_aware_elements
info • Use the null-aware marker '?' rather than a null check via an 'if' • kifi-app/lib/features/transactions/data/repository.dart:172:7 • use_null_aware_elements
info • Use the null-aware marker '?' rather than a null check via an 'if' • kifi-app/lib/features/transactions/data/repository.dart:191:7 • use_null_aware_elements
info • Use the null-aware marker '?' rather than a null check via an 'if' • kifi-app/lib/features/transactions/data/repository.dart:192:7 • use_null_aware_elements
info • Use the null-aware marker '?' rather than a null check via an 'if' • kifi-app/lib/features/transactions/data/repository.dart:193:7 • use_null_aware_elements
info • Use the null-aware marker '?' rather than a null check via an 'if' • kifi-app/lib/features/transactions/data/repository.dart:194:7 • use_null_aware_elements
info • Use the null-aware marker '?' rather than a null check via an 'if' • kifi-app/lib/features/transactions/data/repository.dart:195:7 • use_null_aware_elements
info • Use the null-aware marker '?' rather than a null check via an 'if' • kifi-app/lib/features/transactions/data/repository.dart:196:7 • use_null_aware_elements
info • Use the null-aware marker '?' rather than a null check via an 'if' • kifi-app/lib/features/transactions/data/repository.dart:197:7 • use_null_aware_elements
info • Use the null-aware marker '?' rather than a null check via an 'if' • kifi-app/lib/features/transactions/data/repository.dart:198:7 • use_null_aware_elements
info • Use the null-aware marker '?' rather than a null check via an 'if' • kifi-app/lib/features/transactions/data/repository.dart:199:7 • use_null_aware_elements
info • Use the null-aware marker '?' rather than a null check via an 'if' • kifi-app/lib/features/transactions/data/repository.dart:200:7 • use_null_aware_elements
info • Use the null-aware marker '?' rather than a null check via an 'if' • kifi-app/lib/features/transactions/data/repository.dart:201:7 • use_null_aware_elements
info • 'value' is deprecated and shouldn't be used. Use initialValue instead. This will set the initial value for the form field. This feature was deprecated after v3.33.0-1.0.pre • kifi-app/lib/features/transactions/presentation/add_transaction_screen.dart:297:25 • deprecated_member_use
info • Don't use 'BuildContext's across async gaps, guarded by an unrelated 'mounted' check • kifi-app/lib/features/transactions/presentation/add_transaction_screen.dart:524:54 • use_build_context_synchronously
info • 'value' is deprecated and shouldn't be used. Use initialValue instead. This will set the initial value for the form field. This feature was deprecated after v3.33.0-1.0.pre • kifi-app/lib/features/transactions/presentation/add_transaction_screen.dart:836:21 • deprecated_member_use
info • 'activeColor' is deprecated and shouldn't be used. Use activeThumbColor instead. This feature was deprecated after v3.31.0-2.0.pre • kifi-app/lib/features/transactions/presentation/add_transaction_screen.dart:1048:19 • deprecated_member_use
info • 'value' is deprecated and shouldn't be used. Use initialValue instead. This will set the initial value for the form field. This feature was deprecated after v3.33.0-1.0.pre • kifi-app/lib/features/transactions/presentation/add_transaction_screen.dart:1053:19 • deprecated_member_use
info • 'translate' is deprecated and shouldn't be used. Use translateByVector3, translateByVector4, or translateByDouble instead • kifi-app/lib/features/transactions/presentation/widgets/attachment_gallery_screen.dart:110:11 • deprecated_member_use
info • 'scale' is deprecated and shouldn't be used. Use scaleByVector3, scaleByVector4, or scaleByDouble instead • kifi-app/lib/features/transactions/presentation/widgets/attachment_gallery_screen.dart:111:11 • deprecated_member_use
info • 'value' is deprecated and shouldn't be used. Use initialValue instead. This will set the initial value for the form field. This feature was deprecated after v3.33.0-1.0.pre • kifi-app/lib/features/transactions/presentation/widgets/transaction_filter_sheet.dart:90:17 • deprecated_member_use
info • 'value' is deprecated and shouldn't be used. Use initialValue instead. This will set the initial value for the form field. This feature was deprecated after v3.33.0-1.0.pre • kifi-app/lib/features/transactions/presentation/widgets/transaction_filter_sheet.dart:115:17 • deprecated_member_use
warning • Unused import: '../data/repository.dart' • kifi-app/lib/features/transactions/providers/paginated_transaction_provider.dart:3:8 • unused_import
info • Don't invoke 'print' in production code • kifi-app/lib/features/transactions/providers/paginated_transaction_provider.dart:103:7 • avoid_print
info • 'withOpacity' is deprecated and shouldn't be used. Use .withValues() to avoid precision loss • kifi-app/lib/features/vendor/presentation/add_vendor_sheet.dart:210:58 • deprecated_member_use
warning • Unused import: 'dart:io' • kifi-app/lib/features/vendor/presentation/purchase_order_builder_screen.dart:5:8 • unused_import
warning • Unused import: '../domain/vendor.dart' • kifi-app/lib/features/vendor/presentation/purchase_order_builder_screen.dart:16:8 • unused_import
info • Don't use 'BuildContext's across async gaps • kifi-app/lib/features/vendor/presentation/purchase_order_builder_screen.dart:239:25 • use_build_context_synchronously
warning • Unused import: 'dart:typed_data' • kifi-app/lib/features/vendor/presentation/purchase_order_details_screen.dart:2:8 • unused_import
info • 'Share' is deprecated and shouldn't be used. Use SharePlus instead • kifi-app/lib/features/vendor/presentation/purchase_order_details_screen.dart:542:13 • deprecated_member_use
info • 'shareXFiles' is deprecated and shouldn't be used. Use SharePlus.instance.share() instead • kifi-app/lib/features/vendor/presentation/purchase_order_details_screen.dart:542:19 • deprecated_member_use
info • Statements in an if should be enclosed in a block • kifi-app/lib/features/vendor/presentation/purchase_order_details_screen.dart:547:9 • curly_braces_in_flow_control_structures
info • 'withOpacity' is deprecated and shouldn't be used. Use .withValues() to avoid precision loss • kifi-app/lib/features/vendor/presentation/purchase_order_details_screen.dart:663:48 • deprecated_member_use
info • 'withOpacity' is deprecated and shouldn't be used. Use .withValues() to avoid precision loss • kifi-app/lib/features/vendor/presentation/purchase_order_details_screen.dart:692:49 • deprecated_member_use
warning • The value of the local variable 'darkTheme' isn't used • kifi-app/lib/features/vendor/presentation/purchase_orders_list_screen.dart:59:11 • unused_local_variable
info • 'withOpacity' is deprecated and shouldn't be used. Use .withValues() to avoid precision loss • kifi-app/lib/features/vendor/presentation/purchase_orders_list_screen.dart:146:50 • deprecated_member_use
info • 'withOpacity' is deprecated and shouldn't be used. Use .withValues() to avoid precision loss • kifi-app/lib/features/vendor/presentation/purchase_orders_list_screen.dart:201:45 • deprecated_member_use
warning • The value of the local variable 'darkTheme' isn't used • kifi-app/lib/features/vendor/presentation/vendors_list_screen.dart:20:11 • unused_local_variable
info • 'withOpacity' is deprecated and shouldn't be used. Use .withValues() to avoid precision loss • kifi-app/lib/features/vendor/presentation/vendors_list_screen.dart:85:48 • deprecated_member_use
info • 'withOpacity' is deprecated and shouldn't be used. Use .withValues() to avoid precision loss • kifi-app/lib/features/vendor/presentation/vendors_list_screen.dart:105:66 • deprecated_member_use
warning • Unused import: 'package:dio/dio.dart' • kifi-app/lib/features/vendor/providers/purchase_orders_provider.dart:1:8 • unused_import
warning • Unused import: 'package:dio/dio.dart' • kifi-app/lib/features/vendor/providers/vendors_provider.dart:1:8 • unused_import
warning • Unused import: 'core/network/dio_client.dart' • kifi-app/lib/main.dart:11:8 • unused_import
warning • The stack trace variable 'stacktrace' isn't used and can be removed • kifi-app/lib/main.dart:94:17 • unused_catch_stack
info • Don't invoke 'print' in production code • kifi-app/lib/test_dio.dart:5:3 • avoid_print
error • Target of URI doesn't exist: 'package:flutter/material.dart' • scratch/UpdateTaskDetailsSheet.dart:3:8 • uri_does_not_exist
error • Target of URI doesn't exist: 'package:flutter_riverpod/flutter_riverpod.dart' • scratch/UpdateTaskDetailsSheet.dart:4:8 • uri_does_not_exist
error • Target of URI doesn't exist: 'package:lucide_icons/lucide_icons.dart' • scratch/UpdateTaskDetailsSheet.dart:5:8 • uri_does_not_exist
error • Target of URI doesn't exist: 'package:image_picker/image_picker.dart' • scratch/UpdateTaskDetailsSheet.dart:6:8 • uri_does_not_exist
error • Target of URI doesn't exist: 'package:file_picker/file_picker.dart' • scratch/UpdateTaskDetailsSheet.dart:7:8 • uri_does_not_exist
error • Target of URI doesn't exist: 'package:path_provider/path_provider.dart' • scratch/UpdateTaskDetailsSheet.dart:8:8 • uri_does_not_exist
error • Target of URI doesn't exist: 'package:dio/dio.dart' • scratch/UpdateTaskDetailsSheet.dart:9:8 • uri_does_not_exist
error • Target of URI doesn't exist: 'package:share_plus/share_plus.dart' • scratch/UpdateTaskDetailsSheet.dart:10:8 • uri_does_not_exist
error • Target of URI doesn't exist: 'package:flutter_secure_storage/flutter_secure_storage.dart' • scratch/UpdateTaskDetailsSheet.dart:11:8 • uri_does_not_exist
error • Target of URI doesn't exist: '../../domain/project_task.dart' • scratch/UpdateTaskDetailsSheet.dart:12:8 • uri_does_not_exist
error • Target of URI doesn't exist: '../../providers/project_provider.dart' • scratch/UpdateTaskDetailsSheet.dart:13:8 • uri_does_not_exist
error • Target of URI doesn't exist: '../../../transactions/presentation/widgets/attachment_gallery_screen.dart' • scratch/UpdateTaskDetailsSheet.dart:14:8 • uri_does_not_exist
error • Classes can only extend other classes • scratch/UpdateTaskDetailsSheet.dart:16:32 • extends_non_class
error • Undefined class 'ProjectTask' • scratch/UpdateTaskDetailsSheet.dart:17:9 • undefined_class
error • Undefined class 'Key' • scratch/UpdateTaskDetailsSheet.dart:18:27 • undefined_class
error • The named parameter 'key' isn't defined • scratch/UpdateTaskDetailsSheet.dart:18:66 • undefined_named_parameter
error • Undefined class 'ConsumerState' • scratch/UpdateTaskDetailsSheet.dart:21:3 • undefined_class
warning • The method doesn't override an inherited method • scratch/UpdateTaskDetailsSheet.dart:21:35 • override_on_non_overriding_member
error • Classes can only extend other classes • scratch/UpdateTaskDetailsSheet.dart:24:38 • extends_non_class
error • Undefined class 'TextEditingController' • scratch/UpdateTaskDetailsSheet.dart:25:9 • undefined_class
error • The method 'TextEditingController' isn't defined for the type '_TaskDetailsSheetState' • scratch/UpdateTaskDetailsSheet.dart:25:52 • undefined_method
error • Undefined class 'ImagePicker' • scratch/UpdateTaskDetailsSheet.dart:26:9 • undefined_class
error • The method 'ImagePicker' isn't defined for the type '_TaskDetailsSheetState' • scratch/UpdateTaskDetailsSheet.dart:26:31 • undefined_method
warning • The method doesn't override an inherited method • scratch/UpdateTaskDetailsSheet.dart:33:8 • override_on_non_overriding_member
error • The method 'initState' isn't defined in a superclass of '_TaskDetailsSheetState' • scratch/UpdateTaskDetailsSheet.dart:34:11 • undefined_super_member
error • Const variables must be initialized with a constant value • scratch/UpdateTaskDetailsSheet.dart:39:21 • const_initialized_with_non_constant_value
error • The method 'FlutterSecureStorage' isn't defined for the type '_TaskDetailsSheetState' • scratch/UpdateTaskDetailsSheet.dart:39:21 • undefined_method
error • Undefined name 'mounted' • scratch/UpdateTaskDetailsSheet.dart:41:9 • undefined_identifier
error • The method 'setState' isn't defined for the type '_TaskDetailsSheetState' • scratch/UpdateTaskDetailsSheet.dart:41:18 • undefined_method
error • Undefined class 'XFile' • scratch/UpdateTaskDetailsSheet.dart:45:11 • undefined_class
error • Undefined name 'ImageSource' • scratch/UpdateTaskDetailsSheet.dart:45:58 • undefined_identifier
error • The method 'setState' isn't defined for the type '_TaskDetailsSheetState' • scratch/UpdateTaskDetailsSheet.dart:48:7 • undefined_method
error • Undefined class 'FilePickerResult' • scratch/UpdateTaskDetailsSheet.dart:59:5 • undefined_class
error • Undefined name 'FilePicker' • scratch/UpdateTaskDetailsSheet.dart:59:38 • undefined_identifier
error • The method 'setState' isn't defined for the type '_TaskDetailsSheetState' • scratch/UpdateTaskDetailsSheet.dart:69:7 • undefined_method
error • The method 'setState' isn't defined for the type '_TaskDetailsSheetState' • scratch/UpdateTaskDetailsSheet.dart:82:5 • undefined_method
error • Undefined name 'ref' • scratch/UpdateTaskDetailsSheet.dart:84:20 • undefined_identifier
error • Undefined name 'projectRepositoryProvider' • scratch/UpdateTaskDetailsSheet.dart:84:29 • undefined_identifier
error • Undefined name 'widget' • scratch/UpdateTaskDetailsSheet.dart:86:17 • undefined_identifier
error • The method 'setState' isn't defined for the type '_TaskDetailsSheetState' • scratch/UpdateTaskDetailsSheet.dart:91:7 • undefined_method
error • Undefined name 'ref' • scratch/UpdateTaskDetailsSheet.dart:94:7 • undefined_identifier
error • The method 'projectTaskCommentsProvider' isn't defined for the type '_TaskDetailsSheetState' • scratch/UpdateTaskDetailsSheet.dart:94:22 • undefined_method
error • Undefined name 'widget' • scratch/UpdateTaskDetailsSheet.dart:94:50 • undefined_identifier
error • Undefined name 'mounted' • scratch/UpdateTaskDetailsSheet.dart:96:11 • undefined_identifier
error • Undefined name 'ScaffoldMessenger' • scratch/UpdateTaskDetailsSheet.dart:97:9 • undefined_identifier
error • Undefined name 'context' • scratch/UpdateTaskDetailsSheet.dart:97:30 • undefined_identifier
error • The method 'SnackBar' isn't defined for the type '_TaskDetailsSheetState' • scratch/UpdateTaskDetailsSheet.dart:97:52 • undefined_method
error • The method 'Text' isn't defined for the type '_TaskDetailsSheetState' • scratch/UpdateTaskDetailsSheet.dart:97:70 • undefined_method
error • Undefined name 'mounted' • scratch/UpdateTaskDetailsSheet.dart:100:11 • undefined_identifier
error • The method 'setState' isn't defined for the type '_TaskDetailsSheetState' • scratch/UpdateTaskDetailsSheet.dart:100:20 • undefined_method
error • The method 'setState' isn't defined for the type '_TaskDetailsSheetState' • scratch/UpdateTaskDetailsSheet.dart:111:5 • undefined_method
error • The method 'getTemporaryDirectory' isn't defined for the type '_TaskDetailsSheetState' • scratch/UpdateTaskDetailsSheet.dart:114:25 • undefined_method
error • The method 'Dio' isn't defined for the type '_TaskDetailsSheetState' • scratch/UpdateTaskDetailsSheet.dart:116:19 • undefined_method
error • Undefined name 'mounted' • scratch/UpdateTaskDetailsSheet.dart:123:11 • undefined_identifier
error • Undefined name 'ScaffoldMessenger' • scratch/UpdateTaskDetailsSheet.dart:124:9 • undefined_identifier
error • Undefined name 'context' • scratch/UpdateTaskDetailsSheet.dart:124:30 • undefined_identifier
error • The method 'SnackBar' isn't defined for the type '_TaskDetailsSheetState' • scratch/UpdateTaskDetailsSheet.dart:124:52 • undefined_method
error • The method 'Text' isn't defined for the type '_TaskDetailsSheetState' • scratch/UpdateTaskDetailsSheet.dart:124:70 • undefined_method
error • Undefined name 'Share' • scratch/UpdateTaskDetailsSheet.dart:125:15 • undefined_identifier
error • The method 'XFile' isn't defined for the type '_TaskDetailsSheetState' • scratch/UpdateTaskDetailsSheet.dart:125:34 • undefined_method
error • Undefined name 'mounted' • scratch/UpdateTaskDetailsSheet.dart:128:11 • undefined_identifier
error • Undefined name 'ScaffoldMessenger' • scratch/UpdateTaskDetailsSheet.dart:129:9 • undefined_identifier
error • Undefined name 'context' • scratch/UpdateTaskDetailsSheet.dart:129:30 • undefined_identifier
error • The method 'SnackBar' isn't defined for the type '_TaskDetailsSheetState' • scratch/UpdateTaskDetailsSheet.dart:129:52 • undefined_method
error • The method 'Text' isn't defined for the type '_TaskDetailsSheetState' • scratch/UpdateTaskDetailsSheet.dart:129:70 • undefined_method
error • Undefined name 'mounted' • scratch/UpdateTaskDetailsSheet.dart:132:11 • undefined_identifier
error • The method 'setState' isn't defined for the type '_TaskDetailsSheetState' • scratch/UpdateTaskDetailsSheet.dart:133:9 • undefined_method
error • Undefined class 'Widget' • scratch/UpdateTaskDetailsSheet.dart:139:3 • undefined_class
warning • The method doesn't override an inherited method • scratch/UpdateTaskDetailsSheet.dart:139:10 • override_on_non_overriding_member
error • Undefined class 'BuildContext' • scratch/UpdateTaskDetailsSheet.dart:139:16 • undefined_class
error • Undefined name 'ref' • scratch/UpdateTaskDetailsSheet.dart:140:27 • undefined_identifier
error • The method 'projectTaskCommentsProvider' isn't defined for the type '_TaskDetailsSheetState' • scratch/UpdateTaskDetailsSheet.dart:140:37 • undefined_method
error • Undefined name 'widget' • scratch/UpdateTaskDetailsSheet.dart:140:65 • undefined_identifier
error • The method 'Container' isn't defined for the type '_TaskDetailsSheetState' • scratch/UpdateTaskDetailsSheet.dart:142:12 • undefined_method
error • Undefined name 'MediaQuery' • scratch/UpdateTaskDetailsSheet.dart:143:15 • undefined_identifier
error • The name 'BoxDecoration' isn't a class • scratch/UpdateTaskDetailsSheet.dart:144:25 • creation_with_non_type
error • Undefined name 'Colors' • scratch/UpdateTaskDetailsSheet.dart:145:16 • undefined_identifier
error • Undefined name 'BorderRadius' • scratch/UpdateTaskDetailsSheet.dart:146:23 • undefined_identifier
error • Undefined name 'Radius' • scratch/UpdateTaskDetailsSheet.dart:146:50 • undefined_identifier
error • The method 'Column' isn't defined for the type '_TaskDetailsSheetState' • scratch/UpdateTaskDetailsSheet.dart:148:14 • undefined_method
error • The method 'Expanded' isn't defined for the type '_TaskDetailsSheetState' • scratch/UpdateTaskDetailsSheet.dart:151:11 • undefined_method
error • The name 'Center' isn't a class • scratch/UpdateTaskDetailsSheet.dart:154:52 • creation_with_non_type
error • The method 'Text' isn't defined for the type '_TaskDetailsSheetState' • scratch/UpdateTaskDetailsSheet.dart:154:66 • undefined_method
error • Undefined name 'ListView' • scratch/UpdateTaskDetailsSheet.dart:155:24 • undefined_identifier
error • Undefined name 'EdgeInsets' • scratch/UpdateTaskDetailsSheet.dart:156:34 • undefined_identifier
error • The method 'Card' isn't defined for the type '_TaskDetailsSheetState' • scratch/UpdateTaskDetailsSheet.dart:160:28 • undefined_method
error • Undefined name 'EdgeInsets' • scratch/UpdateTaskDetailsSheet.dart:161:37 • undefined_identifier
error • Undefined name 'Colors' • scratch/UpdateTaskDetailsSheet.dart:162:30 • undefined_identifier
error • The method 'Padding' isn't defined for the type '_TaskDetailsSheetState' • scratch/UpdateTaskDetailsSheet.dart:164:30 • undefined_method
error • Undefined name 'EdgeInsets' • scratch/UpdateTaskDetailsSheet.dart:165:40 • undefined_identifier
error • The method 'Column' isn't defined for the type '_TaskDetailsSheetState' • scratch/UpdateTaskDetailsSheet.dart:166:32 • undefined_method
error • Undefined name 'CrossAxisAlignment' • scratch/UpdateTaskDetailsSheet.dart:167:47 • undefined_identifier
error • The method 'Text' isn't defined for the type '_TaskDetailsSheetState' • scratch/UpdateTaskDetailsSheet.dart:169:29 • undefined_method
error • The name 'TextStyle' isn't a class • scratch/UpdateTaskDetailsSheet.dart:169:58 • creation_with_non_type
error • The name 'SizedBox' isn't a class • scratch/UpdateTaskDetailsSheet.dart:171:37 • creation_with_non_type
error • The method 'Wrap' isn't defined for the type '_TaskDetailsSheetState' • scratch/UpdateTaskDetailsSheet.dart:172:31 • undefined_method
error • Undefined class 'ImageProvider' • scratch/UpdateTaskDetailsSheet.dart:191:37 • undefined_class
error • The method 'MemoryImage' isn't defined for the type '_TaskDetailsSheetState' • scratch/UpdateTaskDetailsSheet.dart:194:51 • undefined_method
error • The method 'NetworkImage' isn't defined for the type '_TaskDetailsSheetState' • scratch/UpdateTaskDetailsSheet.dart:198:45 • undefined_method
error • The name 'AssetImage' isn't a class • scratch/UpdateTaskDetailsSheet.dart:199:51 • creation_with_non_type
error • The name 'ImageProvider' isn't a type, so it can't be used in an 'as' expression • scratch/UpdateTaskDetailsSheet.dart:199:98 • cast_to_non_type
error • The method 'GestureDetector' isn't defined for the type '_TaskDetailsSheetState' • scratch/UpdateTaskDetailsSheet.dart:202:44 • undefined_method
error • The method 'MemoryImage' isn't defined for the type '_TaskDetailsSheetState' • scratch/UpdateTaskDetailsSheet.dart:214:76 • undefined_method
error • The name 'ImageProvider' isn't a type, so it can't be used in an 'as' expression • scratch/UpdateTaskDetailsSheet.dart:214:108 • cast_to_non_type
error • The method 'MemoryImage' isn't defined for the type '_TaskDetailsSheetState' • scratch/UpdateTaskDetailsSheet.dart:216:86 • undefined_method
error • The name 'ImageProvider' isn't a type, so it can't be used in an 'as' expression • scratch/UpdateTaskDetailsSheet.dart:216:137 • cast_to_non_type
error • The method 'NetworkImage' isn't defined for the type '_TaskDetailsSheetState' • scratch/UpdateTaskDetailsSheet.dart:218:52 • undefined_method
error • The name 'ImageProvider' isn't a type, so it can't be used in an 'as' expression • scratch/UpdateTaskDetailsSheet.dart:218:122 • cast_to_non_type
error • Undefined name 'Navigator' • scratch/UpdateTaskDetailsSheet.dart:235:41 • undefined_identifier
error • The method 'MaterialPageRoute' isn't defined for the type '_TaskDetailsSheetState' • scratch/UpdateTaskDetailsSheet.dart:237:43 • undefined_method
error • The method 'AttachmentGalleryScreen' isn't defined for the type '_TaskDetailsSheetState' • scratch/UpdateTaskDetailsSheet.dart:238:67 • undefined_method
error • The method 'ClipRRect' isn't defined for the type '_TaskDetailsSheetState' • scratch/UpdateTaskDetailsSheet.dart:245:46 • undefined_method
error • Undefined name 'BorderRadius' • scratch/UpdateTaskDetailsSheet.dart:246:55 • undefined_identifier
error • The method 'Image' isn't defined for the type '_TaskDetailsSheetState' • scratch/UpdateTaskDetailsSheet.dart:247:48 • undefined_method
error • Undefined name 'BoxFit' • scratch/UpdateTaskDetailsSheet.dart:251:48 • undefined_identifier
error • The method 'GestureDetector' isn't defined for the type '_TaskDetailsSheetState' • scratch/UpdateTaskDetailsSheet.dart:261:44 • undefined_method
error • The method 'Container' isn't defined for the type '_TaskDetailsSheetState' • scratch/UpdateTaskDetailsSheet.dart:267:46 • undefined_method
error • The method 'BoxDecoration' isn't defined for the type '_TaskDetailsSheetState' • scratch/UpdateTaskDetailsSheet.dart:270:53 • undefined_method
error • Undefined name 'Colors' • scratch/UpdateTaskDetailsSheet.dart:271:50 • undefined_identifier
error • Undefined name 'BorderRadius' • scratch/UpdateTaskDetailsSheet.dart:272:57 • undefined_identifier
error • Undefined name 'Border' • scratch/UpdateTaskDetailsSheet.dart:273:51 • undefined_identifier
error • Undefined name 'Colors' • scratch/UpdateTaskDetailsSheet.dart:273:69 • undefined_identifier
error • The method 'Column' isn't defined for the type '_TaskDetailsSheetState' • scratch/UpdateTaskDetailsSheet.dart:275:48 • undefined_method
error • Undefined name 'MainAxisAlignment' • scratch/UpdateTaskDetailsSheet.dart:276:62 • undefined_identifier
error • The name 'SizedBox' isn't a class • scratch/UpdateTaskDetailsSheet.dart:279:57 • creation_with_non_type
error • The method 'CircularProgressIndicator' isn't defined for the type '_TaskDetailsSheetState' • scratch/UpdateTaskDetailsSheet.dart:279:96 • undefined_method
error • The name 'Icon' isn't a class • scratch/UpdateTaskDetailsSheet.dart:280:57 • creation_with_non_type
error • Undefined name 'LucideIcons' • scratch/UpdateTaskDetailsSheet.dart:280:62 • undefined_identifier
error • Undefined name 'Colors' • scratch/UpdateTaskDetailsSheet.dart:280:91 • undefined_identifier
error • The name 'SizedBox' isn't a class • scratch/UpdateTaskDetailsSheet.dart:281:51 • creation_with_non_type
error • The method 'Padding' isn't defined for the type '_TaskDetailsSheetState' • scratch/UpdateTaskDetailsSheet.dart:282:45 • undefined_method
error • Undefined name 'EdgeInsets' • scratch/UpdateTaskDetailsSheet.dart:283:62 • undefined_identifier
error • The method 'Text' isn't defined for the type '_TaskDetailsSheetState' • scratch/UpdateTaskDetailsSheet.dart:284:54 • undefined_method
error • The name 'TextStyle' isn't a class • scratch/UpdateTaskDetailsSheet.dart:286:62 • creation_with_non_type
error • Undefined name 'TextOverflow' • scratch/UpdateTaskDetailsSheet.dart:288:59 • undefined_identifier
error • The name 'Center' isn't a class • scratch/UpdateTaskDetailsSheet.dart:306:36 • creation_with_non_type
error • The method 'CircularProgressIndicator' isn't defined for the type '_TaskDetailsSheetState' • scratch/UpdateTaskDetailsSheet.dart:306:50 • undefined_method
error • The method 'Center' isn't defined for the type '_TaskDetailsSheetState' • scratch/UpdateTaskDetailsSheet.dart:307:38 • undefined_method
error • The method 'Text' isn't defined for the type '_TaskDetailsSheetState' • scratch/UpdateTaskDetailsSheet.dart:307:52 • undefined_method
error • Undefined class 'Widget' • scratch/UpdateTaskDetailsSheet.dart:316:3 • undefined_class
error • Undefined class 'BuildContext' • scratch/UpdateTaskDetailsSheet.dart:316:23 • undefined_class
error • The method 'Container' isn't defined for the type '_TaskDetailsSheetState' • scratch/UpdateTaskDetailsSheet.dart:317:12 • undefined_method
error • Undefined name 'EdgeInsets' • scratch/UpdateTaskDetailsSheet.dart:318:22 • undefined_identifier
error • The method 'BoxDecoration' isn't defined for the type '_TaskDetailsSheetState' • scratch/UpdateTaskDetailsSheet.dart:319:19 • undefined_method
error • The method 'Border' isn't defined for the type '_TaskDetailsSheetState' • scratch/UpdateTaskDetailsSheet.dart:319:41 • undefined_method
error • The method 'BorderSide' isn't defined for the type '_TaskDetailsSheetState' • scratch/UpdateTaskDetailsSheet.dart:319:56 • undefined_method
error • Undefined name 'Colors' • scratch/UpdateTaskDetailsSheet.dart:319:74 • undefined_identifier
error • The method 'Row' isn't defined for the type '_TaskDetailsSheetState' • scratch/UpdateTaskDetailsSheet.dart:320:14 • undefined_method
error • Undefined name 'MainAxisAlignment' • scratch/UpdateTaskDetailsSheet.dart:321:28 • undefined_identifier
error • The method 'Expanded' isn't defined for the type '_TaskDetailsSheetState' • scratch/UpdateTaskDetailsSheet.dart:323:11 • undefined_method
error • The method 'Column' isn't defined for the type '_TaskDetailsSheetState' • scratch/UpdateTaskDetailsSheet.dart:324:20 • undefined_method
error • Undefined name 'CrossAxisAlignment' • scratch/UpdateTaskDetailsSheet.dart:325:35 • undefined_identifier
error • The method 'Text' isn't defined for the type '_TaskDetailsSheetState' • scratch/UpdateTaskDetailsSheet.dart:327:17 • undefined_method
error • Undefined name 'widget' • scratch/UpdateTaskDetailsSheet.dart:327:22 • undefined_identifier
error • The name 'TextStyle' isn't a class • scratch/UpdateTaskDetailsSheet.dart:327:54 • creation_with_non_type
error • Undefined name 'FontWeight' • scratch/UpdateTaskDetailsSheet.dart:327:90 • undefined_identifier
error • Undefined name 'widget' • scratch/UpdateTaskDetailsSheet.dart:328:21 • undefined_identifier
error • Undefined name 'widget' • scratch/UpdateTaskDetailsSheet.dart:328:56 • undefined_identifier
error • The method 'Text' isn't defined for the type '_TaskDetailsSheetState' • scratch/UpdateTaskDetailsSheet.dart:329:19 • undefined_method
error • Undefined name 'widget' • scratch/UpdateTaskDetailsSheet.dart:329:24 • undefined_identifier
error • The name 'TextStyle' isn't a class • scratch/UpdateTaskDetailsSheet.dart:329:63 • creation_with_non_type
error • Undefined name 'Colors' • scratch/UpdateTaskDetailsSheet.dart:329:80 • undefined_identifier
error • The method 'IconButton' isn't defined for the type '_TaskDetailsSheetState' • scratch/UpdateTaskDetailsSheet.dart:333:11 • undefined_method
error • The name 'Icon' isn't a class • scratch/UpdateTaskDetailsSheet.dart:333:34 • creation_with_non_type
error • Undefined name 'LucideIcons' • scratch/UpdateTaskDetailsSheet.dart:333:39 • undefined_identifier
error • Undefined name 'Navigator' • scratch/UpdateTaskDetailsSheet.dart:333:72 • undefined_identifier
error • Undefined class 'Widget' • scratch/UpdateTaskDetailsSheet.dart:339:3 • undefined_class
error • The method 'Container' isn't defined for the type '_TaskDetailsSheetState' • scratch/UpdateTaskDetailsSheet.dart:340:12 • undefined_method
error • Undefined name 'EdgeInsets' • scratch/UpdateTaskDetailsSheet.dart:341:16 • undefined_identifier
error • Undefined name 'MediaQuery' • scratch/UpdateTaskDetailsSheet.dart:342:17 • undefined_identifier
error • Undefined name 'context' • scratch/UpdateTaskDetailsSheet.dart:342:31 • undefined_identifier
error • The method 'BoxDecoration' isn't defined for the type '_TaskDetailsSheetState' • scratch/UpdateTaskDetailsSheet.dart:347:19 • undefined_method
error • Undefined name 'Colors' • scratch/UpdateTaskDetailsSheet.dart:348:16 • undefined_identifier
error • The method 'Border' isn't defined for the type '_TaskDetailsSheetState' • scratch/UpdateTaskDetailsSheet.dart:349:17 • undefined_method
error • The method 'BorderSide' isn't defined for the type '_TaskDetailsSheetState' • scratch/UpdateTaskDetailsSheet.dart:349:29 • undefined_method
error • Undefined name 'Colors' • scratch/UpdateTaskDetailsSheet.dart:349:47 • undefined_identifier
error • The method 'Column' isn't defined for the type '_TaskDetailsSheetState' • scratch/UpdateTaskDetailsSheet.dart:351:14 • undefined_method
error • Undefined name 'CrossAxisAlignment' • scratch/UpdateTaskDetailsSheet.dart:352:29 • undefined_identifier
error • The method 'Padding' isn't defined for the type '_TaskDetailsSheetState' • scratch/UpdateTaskDetailsSheet.dart:355:13 • undefined_method
error • Undefined name 'EdgeInsets' • scratch/UpdateTaskDetailsSheet.dart:356:30 • undefined_identifier
error • The method 'Wrap' isn't defined for the type '_TaskDetailsSheetState' • scratch/UpdateTaskDetailsSheet.dart:357:22 • undefined_method
error • The method 'Stack' isn't defined for the type '_TaskDetailsSheetState' • scratch/UpdateTaskDetailsSheet.dart:363:26 • undefined_method
error • The method 'Container' isn't defined for the type '_TaskDetailsSheetState' • scratch/UpdateTaskDetailsSheet.dart:365:23 • undefined_method
error • The method 'BoxDecoration' isn't defined for the type '_TaskDetailsSheetState' • scratch/UpdateTaskDetailsSheet.dart:368:37 • undefined_method
error • Undefined name 'Colors' • scratch/UpdateTaskDetailsSheet.dart:369:34 • undefined_identifier
error • Undefined name 'BorderRadius' • scratch/UpdateTaskDetailsSheet.dart:370:41 • undefined_identifier
error • The method 'ClipRRect' isn't defined for the type '_TaskDetailsSheetState' • scratch/UpdateTaskDetailsSheet.dart:373:29 • undefined_method
error • Undefined name 'BorderRadius' • scratch/UpdateTaskDetailsSheet.dart:374:45 • undefined_identifier
error • Undefined name 'Image' • scratch/UpdateTaskDetailsSheet.dart:375:38 • undefined_identifier
error • Undefined name 'BoxFit' • scratch/UpdateTaskDetailsSheet.dart:377:38 • undefined_identifier
error • The method 'Column' isn't defined for the type '_TaskDetailsSheetState' • scratch/UpdateTaskDetailsSheet.dart:380:29 • undefined_method
error • Undefined name 'MainAxisAlignment' • scratch/UpdateTaskDetailsSheet.dart:381:50 • undefined_identifier
error • The name 'Icon' isn't a class • scratch/UpdateTaskDetailsSheet.dart:383:39 • creation_with_non_type
error • Undefined name 'LucideIcons' • scratch/UpdateTaskDetailsSheet.dart:383:44 • undefined_identifier
error • Undefined name 'Colors' • scratch/UpdateTaskDetailsSheet.dart:383:83 • undefined_identifier
error • The method 'Text' isn't defined for the type '_TaskDetailsSheetState' • scratch/UpdateTaskDetailsSheet.dart:384:33 • undefined_method
error • The name 'TextStyle' isn't a class • scratch/UpdateTaskDetailsSheet.dart:384:74 • creation_with_non_type
error • Undefined name 'TextOverflow' • scratch/UpdateTaskDetailsSheet.dart:384:121 • undefined_identifier
error • The method 'Positioned' isn't defined for the type '_TaskDetailsSheetState' • scratch/UpdateTaskDetailsSheet.dart:388:23 • undefined_method
error • The method 'GestureDetector' isn't defined for the type '_TaskDetailsSheetState' • scratch/UpdateTaskDetailsSheet.dart:391:32 • undefined_method
error • The method 'setState' isn't defined for the type '_TaskDetailsSheetState' • scratch/UpdateTaskDetailsSheet.dart:393:29 • undefined_method
error • The method 'Container' isn't defined for the type '_TaskDetailsSheetState' • scratch/UpdateTaskDetailsSheet.dart:397:34 • undefined_method
error • Undefined name 'Colors' • scratch/UpdateTaskDetailsSheet.dart:398:36 • undefined_identifier
error • The name 'Icon' isn't a class • scratch/UpdateTaskDetailsSheet.dart:399:42 • creation_with_non_type
error • Undefined name 'LucideIcons' • scratch/UpdateTaskDetailsSheet.dart:399:47 • undefined_identifier
error • Undefined name 'Colors' • scratch/UpdateTaskDetailsSheet.dart:399:79 • undefined_identifier
error • The method 'Row' isn't defined for the type '_TaskDetailsSheetState' • scratch/UpdateTaskDetailsSheet.dart:408:11 • undefined_method
error • The method 'IconButton' isn't defined for the type '_TaskDetailsSheetState' • scratch/UpdateTaskDetailsSheet.dart:410:15 • undefined_method
error • The name 'Icon' isn't a class • scratch/UpdateTaskDetailsSheet.dart:411:29 • creation_with_non_type
error • Undefined name 'LucideIcons' • scratch/UpdateTaskDetailsSheet.dart:411:34 • undefined_identifier
error • The method 'IconButton' isn't defined for the type '_TaskDetailsSheetState' • scratch/UpdateTaskDetailsSheet.dart:414:15 • undefined_method
error • The name 'Icon' isn't a class • scratch/UpdateTaskDetailsSheet.dart:415:29 • creation_with_non_type
error • Undefined name 'LucideIcons' • scratch/UpdateTaskDetailsSheet.dart:415:34 • undefined_identifier
error • The method 'Expanded' isn't defined for the type '_TaskDetailsSheetState' • scratch/UpdateTaskDetailsSheet.dart:418:15 • undefined_method
error • The method 'TextField' isn't defined for the type '_TaskDetailsSheetState' • scratch/UpdateTaskDetailsSheet.dart:419:24 • undefined_method
error • The name 'InputDecoration' isn't a class • scratch/UpdateTaskDetailsSheet.dart:421:37 • creation_with_non_type
error • Undefined name 'InputBorder' • scratch/UpdateTaskDetailsSheet.dart:423:29 • undefined_identifier
error • The name 'Padding' isn't a class • scratch/UpdateTaskDetailsSheet.dart:428:27 • creation_with_non_type
error • Undefined name 'EdgeInsets' • scratch/UpdateTaskDetailsSheet.dart:428:44 • undefined_identifier
error • The method 'SizedBox' isn't defined for the type '_TaskDetailsSheetState' • scratch/UpdateTaskDetailsSheet.dart:428:73 • undefined_method
error • The method 'CircularProgressIndicator' isn't defined for the type '_TaskDetailsSheetState' • scratch/UpdateTaskDetailsSheet.dart:428:112 • undefined_method
error • The method 'IconButton' isn't defined for the type '_TaskDetailsSheetState' • scratch/UpdateTaskDetailsSheet.dart:429:21 • undefined_method
error • The name 'Icon' isn't a class • scratch/UpdateTaskDetailsSheet.dart:430:35 • creation_with_non_type
error • Undefined name 'LucideIcons' • scratch/UpdateTaskDetailsSheet.dart:430:40 • undefined_identifier
error • Undefined name 'Colors' • scratch/UpdateTaskDetailsSheet.dart:430:65 • undefined_identifier

17
kifi-api/TestJwt.java Normal file
View File

@@ -0,0 +1,17 @@
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.security.Keys;
import java.util.HashMap;
public class TestJwt {
public static void main(String[] args) {
try {
byte[] key = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa".getBytes();
HashMap<String, Object> claims = new HashMap<>();
claims.put("userId", 1L);
String token = Jwts.builder().claims(claims).signWith(Keys.hmacShaKeyFor(key)).compact();
Long parsed = Jwts.parser().verifyWith(Keys.hmacShaKeyFor(key)).build().parseSignedClaims(token).getPayload().get("userId", Long.class);
System.out.println("Parsed: " + parsed);
} catch(Exception e) {
e.printStackTrace();
}
}
}

View File

@@ -6,7 +6,9 @@ USERNAME="technobee_admin"
PASSWORD='M@tr!x#149@dm!N' PASSWORD='M@tr!x#149@dm!N'
IMAGE_NAME="kifi-api" IMAGE_NAME="kifi-api"
TAG="latest" TAG="latest"
TAG_ONE="kifi-v2"
FULL_IMAGE_NAME="$REGISTRY/$IMAGE_NAME:$TAG" FULL_IMAGE_NAME="$REGISTRY/$IMAGE_NAME:$TAG"
FULL_IMAGE_NAME_ONE="$REGISTRY/$IMAGE_NAME:$TAG_ONE"
# Stop on any error # Stop on any error
set -e set -e
@@ -14,7 +16,7 @@ set -e
echo "Logging into Docker registry: $REGISTRY..." echo "Logging into Docker registry: $REGISTRY..."
echo "$PASSWORD" | docker login "$REGISTRY" -u "$USERNAME" --password-stdin echo "$PASSWORD" | docker login "$REGISTRY" -u "$USERNAME" --password-stdin
echo "Building and pushing Docker image for linux/amd64: $FULL_IMAGE_NAME..." echo "Building and pushing Docker image for linux/amd64: $FULL_IMAGE_NAME and $FULL_IMAGE_NAME_ONE..."
docker buildx build --platform linux/amd64 -t "$FULL_IMAGE_NAME" --push . docker buildx build --no-cache --platform linux/amd64 -t "$FULL_IMAGE_NAME" -t "$FULL_IMAGE_NAME_ONE" --push .
echo "Done! Image built and pushed successfully." echo "Done! Image built and pushed successfully."

20
kifi-api/build_n_push_v2.sh Executable file
View File

@@ -0,0 +1,20 @@
#!/bin/bash
# Configuration
REGISTRY="hub.technobeesolutions.in"
USERNAME="technobee_admin"
PASSWORD='M@tr!x#149@dm!N'
IMAGE_NAME="kifi-api"
TAG="kifi-one"
FULL_IMAGE_NAME="$REGISTRY/$IMAGE_NAME:$TAG"
# Stop on any error
set -e
echo "Logging into Docker registry: $REGISTRY..."
echo "$PASSWORD" | docker login "$REGISTRY" -u "$USERNAME" --password-stdin
echo "Building and pushing Docker image for linux/amd64: $FULL_IMAGE_NAME..."
docker buildx build --platform linux/amd64 -t "$FULL_IMAGE_NAME" --push .
echo "Done! Image built and pushed successfully."

View File

@@ -0,0 +1,37 @@
import re
import os
files = [
'src/main/java/com/kifi/api/controller/customer/CustomerController.java',
'src/main/java/com/kifi/api/controller/invoice/InvoiceController.java'
]
for file in files:
with open(file, 'r') as f:
content = f.read()
# Add import org.springframework.security.core.Authentication; if not present
if 'import org.springframework.security.core.Authentication;' not in content:
content = content.replace('import org.springframework.web.bind.annotation.*;',
'import org.springframework.security.core.Authentication;\nimport org.springframework.web.bind.annotation.*;')
# Replace @RequestAttribute("userId") Long userId, with Authentication authentication,
content = content.replace('@RequestAttribute("userId") Long userId,', 'Authentication authentication,')
# Replace @RequestAttribute("userId") Long userId with Authentication authentication
content = content.replace('@RequestAttribute("userId") Long userId', 'Authentication authentication')
# Now, find all method declarations that have (..., Authentication authentication, ...) {
# and insert Long userId = Long.valueOf(authentication.getDetails().toString()); right after the {
# We can use regex to find method bodies
pattern = re.compile(r'(public\s+[^\(]+\([^\)]*Authentication authentication[^\)]*\)\s*\{)')
def replacer(match):
return match.group(1) + '\n Long userId = Long.valueOf(authentication.getDetails().toString());'
content = pattern.sub(replacer, content)
with open(file, 'w') as f:
f.write(content)
print("Controllers fixed!")

0
kifi-api/kifi.db Normal file
View File

0
kifi-api/kifi_local.db Normal file
View File

6
kifi-api/scratch.dart Normal file
View File

@@ -0,0 +1,6 @@
import 'dart:convert';
import 'package:http/http.dart' as http;
void main() async {
final token = "YOUR_TOKEN"; // I don't have the token
}

7
kifi-api/scratch.java Normal file
View File

@@ -0,0 +1,7 @@
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class scratch {
public static void main(String[] args) {
System.out.println("Wait");
}
}

View File

@@ -14,6 +14,12 @@ import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.server.SecurityWebFilterChain; import org.springframework.security.web.server.SecurityWebFilterChain;
import reactor.core.publisher.Mono; import reactor.core.publisher.Mono;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.reactive.CorsConfigurationSource;
import org.springframework.web.cors.reactive.UrlBasedCorsConfigurationSource;
import java.util.Arrays;
import java.util.List;
@Configuration @Configuration
@EnableWebFluxSecurity @EnableWebFluxSecurity
@RequiredArgsConstructor @RequiredArgsConstructor
@@ -27,9 +33,25 @@ public class SecurityConfig {
return new BCryptPasswordEncoder(); return new BCryptPasswordEncoder();
} }
@Bean
public CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOriginPatterns(List.of("*"));
configuration.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE", "OPTIONS", "PATCH", "HEAD"));
configuration.setAllowedHeaders(List.of("*"));
configuration.setExposedHeaders(List.of("*"));
configuration.setAllowCredentials(true);
configuration.setMaxAge(3600L);
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
@Bean @Bean
public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http) { public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http) {
return http return http
.cors(corsSpec -> corsSpec.configurationSource(corsConfigurationSource()))
.exceptionHandling(exceptionHandlingSpec -> exceptionHandlingSpec .exceptionHandling(exceptionHandlingSpec -> exceptionHandlingSpec
.authenticationEntryPoint((swe, e) -> .authenticationEntryPoint((swe, e) ->
Mono.fromRunnable(() -> swe.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED)) Mono.fromRunnable(() -> swe.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED))
@@ -45,8 +67,11 @@ public class SecurityConfig {
.securityContextRepository(securityContextRepository) .securityContextRepository(securityContextRepository)
.authorizeExchange(exchange -> exchange .authorizeExchange(exchange -> exchange
.pathMatchers(HttpMethod.OPTIONS).permitAll() .pathMatchers(HttpMethod.OPTIONS).permitAll()
.pathMatchers("/api/kifi/auth/**").permitAll() .pathMatchers("/api/kifi-v2/auth/**", "/api/kifi-v2/categories/**", "/api/kifi-v2/purchase-orders/test/**").permitAll()
.pathMatchers("/api/kifi/health/**").permitAll() .pathMatchers("/api/kifi-v2/health/**", "/api/kifi-v2/upload/view**").permitAll()
.pathMatchers("/api/kifi-v2/wallets/test/**").permitAll()
.pathMatchers("/public/legal/**").permitAll()
.pathMatchers("/test/**").permitAll()
.anyExchange().authenticated() .anyExchange().authenticated()
) )
.build(); .build();

View File

@@ -9,6 +9,10 @@ public class WebClientConfig {
@Bean @Bean
public WebClient.Builder webClientBuilder() { public WebClient.Builder webClientBuilder() {
return WebClient.builder(); return WebClient
.builder().codecs(configurer ->
configurer.defaultCodecs()
.maxInMemorySize(10 * 1024 * 1024)
);
} }
} }

View File

@@ -13,7 +13,7 @@ import reactor.core.publisher.Mono;
import java.util.Map; import java.util.Map;
@RestController @RestController
@RequestMapping("/api/kifi/auth") @RequestMapping("/api/kifi-v2/auth")
@RequiredArgsConstructor @RequiredArgsConstructor
public class AuthController { public class AuthController {

View File

@@ -12,7 +12,7 @@ import reactor.core.publisher.Mono;
import java.util.List; import java.util.List;
@RestController @RestController
@RequestMapping("/api/kifi/budgets") @RequestMapping("/api/kifi-v2/budgets")
@RequiredArgsConstructor @RequiredArgsConstructor
public class BudgetController { public class BudgetController {
private final BudgetService budgetService; private final BudgetService budgetService;

View File

@@ -11,7 +11,7 @@ import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Mono; import reactor.core.publisher.Mono;
@RestController @RestController
@RequestMapping("/api/kifi/categories") @RequestMapping("/api/kifi-v2/categories")
@RequiredArgsConstructor @RequiredArgsConstructor
public class CategoryController { public class CategoryController {
private final CategoryService categoryService; private final CategoryService categoryService;

View File

@@ -8,7 +8,7 @@ import reactor.core.publisher.Mono;
import java.util.Map; import java.util.Map;
@RestController @RestController
@RequestMapping("/api/kifi/health") @RequestMapping("/api/kifi-v2/health")
public class HealthController { public class HealthController {
@GetMapping @GetMapping

View File

@@ -0,0 +1,38 @@
package com.kifi.api.controller;
import org.springframework.core.io.ClassPathResource;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.util.StreamUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Mono;
import java.nio.charset.StandardCharsets;
@RestController
@RequestMapping("/public/legal")
public class LegalController {
@GetMapping(value = "/terms", produces = MediaType.TEXT_HTML_VALUE)
public Mono<ResponseEntity<String>> getTerms() {
return loadResource("policies/terms-and-conditions.html");
}
@GetMapping(value = "/privacy", produces = MediaType.TEXT_HTML_VALUE)
public Mono<ResponseEntity<String>> getPrivacy() {
return loadResource("policies/privacy-policy.html");
}
private Mono<ResponseEntity<String>> loadResource(String path) {
return Mono.fromCallable(() -> {
ClassPathResource resource = new ClassPathResource(path);
if (resource.exists()) {
String content = StreamUtils.copyToString(resource.getInputStream(), StandardCharsets.UTF_8);
return ResponseEntity.ok().contentType(MediaType.TEXT_HTML).body(content);
}
return ResponseEntity.notFound().build();
});
}
}

View File

@@ -0,0 +1,148 @@
package com.kifi.api.controller;
import com.kifi.api.entity.project.Project;
import com.kifi.api.entity.project.ProjectTask;
import com.kifi.api.entity.project.ProjectTaskComment;
import com.kifi.api.service.ProjectService;
import lombok.Data;
import lombok.RequiredArgsConstructor;
import org.springframework.security.core.Authentication;
import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
@RestController
@RequestMapping("/api/kifi-v2/projects")
@RequiredArgsConstructor
public class ProjectController {
private final ProjectService projectService;
@GetMapping
public Flux<Project> getProjects(Authentication authentication) {
Long userId = Long.valueOf(authentication.getDetails().toString());
return projectService.getProjectsByUser(userId);
}
@PostMapping
public Mono<Project> createProject(@RequestBody CreateProjectRequest request, Authentication authentication) {
Long userId = Long.valueOf(authentication.getDetails().toString());
return projectService.createProject(
userId,
request.getName(),
request.getDescription(),
request.getCustomerId(),
request.getBudget()
);
}
@PutMapping("/{projectId}")
public Mono<Project> updateProject(@PathVariable Long projectId, @RequestBody CreateProjectRequest request, Authentication authentication) {
Long userId = Long.valueOf(authentication.getDetails().toString());
return projectService.updateProject(
projectId,
userId,
request.getName(),
request.getDescription(),
request.getCustomerId(),
request.getBudget(),
request.getStatus()
);
}
@DeleteMapping("/{projectId}")
public Mono<Void> deleteProject(@PathVariable Long projectId, Authentication authentication) {
Long userId = Long.valueOf(authentication.getDetails().toString());
return projectService.deleteProject(projectId, userId);
}
@GetMapping("/{projectId}/tasks")
public Flux<ProjectTask> getTasks(@PathVariable Long projectId) {
return projectService.getTasksByProject(projectId);
}
@PostMapping("/{projectId}/tasks")
public Mono<ProjectTask> createTask(@PathVariable Long projectId, @RequestBody CreateTaskRequest request) {
return projectService.createTask(
projectId,
request.getTitle(),
request.getDescription(),
request.getAssigneeName(),
request.getAssigneeUserId(),
request.getIsBillable(),
request.getHourlyRate()
);
}
@PutMapping("/tasks/{taskId}")
public Mono<ProjectTask> updateTask(@PathVariable Long taskId, @RequestBody CreateTaskRequest request) {
return projectService.updateTask(
taskId,
request.getTitle(),
request.getDescription(),
request.getAssigneeName(),
request.getAssigneeUserId(),
request.getStatus(),
request.getIsBillable(),
request.getHourlyRate(),
request.getHoursLogged()
);
}
@DeleteMapping("/tasks/{taskId}")
public Mono<Void> deleteTask(@PathVariable Long taskId) {
return projectService.deleteTask(taskId);
}
@GetMapping("/tasks/{taskId}/comments")
public Flux<ProjectTaskComment> getComments(@PathVariable Long taskId) {
return projectService.getCommentsForTask(taskId);
}
@PostMapping("/tasks/{taskId}/comments")
public Mono<ProjectTaskComment> addComment(
@PathVariable Long taskId,
@RequestBody CreateCommentRequest request,
Authentication authentication) {
Long userId = Long.valueOf(authentication.getDetails().toString());
return projectService.addComment(taskId, userId, request.getContent(), request.getImagesJson());
}
@GetMapping("/tasks/attachments/download")
public Mono<org.springframework.http.ResponseEntity<byte[]>> downloadAttachment(
@RequestParam String filePath,
@RequestParam String contentType) {
return projectService.downloadAttachment(contentType, filePath)
.map(res -> org.springframework.http.ResponseEntity.ok()
.header(org.springframework.http.HttpHeaders.CONTENT_TYPE, contentType)
.body(java.util.Base64.getDecoder().decode(res.getBase64Content())));
}
@Data
static class CreateProjectRequest {
private String name;
private String description;
private Long customerId;
private java.math.BigDecimal budget;
private String status;
}
@Data
static class CreateTaskRequest {
private String title;
private String description;
private String assigneeName;
private Long assigneeUserId;
private String status;
private Boolean isBillable;
private java.math.BigDecimal hourlyRate;
private java.math.BigDecimal hoursLogged;
}
@Data
static class CreateCommentRequest {
private String content;
private String imagesJson;
}
}

View File

@@ -12,7 +12,7 @@ import java.util.List;
import reactor.core.publisher.Mono; import reactor.core.publisher.Mono;
@RestController @RestController
@RequestMapping("/api/kifi/recurring-transactions") @RequestMapping("/api/kifi-v2/recurring-transactions")
@RequiredArgsConstructor @RequiredArgsConstructor
public class RecurringTransactionController { public class RecurringTransactionController {

View File

@@ -12,7 +12,7 @@ import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Mono; import reactor.core.publisher.Mono;
@RestController @RestController
@RequestMapping("/api/kifi/reports") @RequestMapping("/api/kifi-v2/reports")
@RequiredArgsConstructor @RequiredArgsConstructor
public class ReportController { public class ReportController {
private final ReportService reportService; private final ReportService reportService;

View File

@@ -0,0 +1,45 @@
package com.kifi.api.controller;
import com.kifi.api.dto.SetupRequestDTO;
import com.kifi.api.service.SetupService;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.Authentication;
import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Mono;
import java.util.Map;
@RestController
@RequestMapping("/api/kifi-v2/account")
@RequiredArgsConstructor
public class SetupController {
private final SetupService setupService;
@GetMapping("/setup/status")
public Mono<ResponseEntity<Map<String, String>>> getSetupStatus(Authentication authentication) {
Long userId = Long.valueOf(authentication.getDetails().toString());
return setupService.getSetupStatus(userId)
.map(ResponseEntity::ok);
}
@GetMapping("/username/availability")
public Mono<ResponseEntity<Map<String, Boolean>>> isUsernameAvailable(@RequestParam String username) {
return setupService.isUsernameAvailable(username)
.map(available -> ResponseEntity.ok(Map.of("available", available)));
}
@PostMapping("/setup")
public Mono<ResponseEntity<Map<String, String>>> completeSetup(Authentication authentication, @RequestBody SetupRequestDTO request, org.springframework.web.server.ServerWebExchange exchange) {
Long userId = Long.valueOf(authentication.getDetails().toString());
String userAgent = exchange.getRequest().getHeaders().getFirst(org.springframework.http.HttpHeaders.USER_AGENT);
String ipAddress = exchange.getRequest().getHeaders().getFirst("X-Forwarded-For");
if (ipAddress == null && exchange.getRequest().getRemoteAddress() != null) {
ipAddress = exchange.getRequest().getRemoteAddress().getAddress().getHostAddress();
}
return setupService.completeSetup(userId, request, ipAddress, userAgent)
.map(message -> ResponseEntity.ok(Map.of("message", message)))
.onErrorResume(e -> Mono.just(ResponseEntity.badRequest().body(Map.of("message", e.getMessage()))));
}
}

View File

@@ -15,7 +15,7 @@ import java.util.List;
import reactor.core.publisher.Mono; import reactor.core.publisher.Mono;
@RestController @RestController
@RequestMapping("/api/kifi/transactions") @RequestMapping("/api/kifi-v2/transactions")
@RequiredArgsConstructor @RequiredArgsConstructor
public class TransactionController { public class TransactionController {
private final TransactionService transactionService; private final TransactionService transactionService;

View File

@@ -0,0 +1,62 @@
package com.kifi.api.controller;
import com.kifi.api.service.MinioServiceClient;
import lombok.RequiredArgsConstructor;
import org.springframework.core.io.buffer.DataBufferUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseEntity;
import org.springframework.http.codec.multipart.FilePart;
import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Mono;
import java.util.Base64;
import java.util.Map;
import java.util.UUID;
@RestController
@RequestMapping("/api/kifi-v2/upload")
@RequiredArgsConstructor
public class UploadController {
private final MinioServiceClient minioServiceClient;
@PostMapping
public Mono<Map<String, String>> upload(@RequestPart("file") Mono<FilePart> filePartMono) {
return filePartMono.flatMap(filePart ->
DataBufferUtils.join(filePart.content())
.flatMap(dataBuffer -> {
byte[] bytes = new byte[dataBuffer.readableByteCount()];
dataBuffer.read(bytes);
DataBufferUtils.release(dataBuffer);
String base64 = Base64.getEncoder().encodeToString(bytes);
String fileName = UUID.randomUUID().toString() + "-" + filePart.filename();
return minioServiceClient.uploadFile(
"general",
filePart.headers().getContentType() != null ? filePart.headers().getContentType().toString() : "application/octet-stream",
fileName,
base64
).map(response -> Map.of("url", response.getFilePath()));
})
);
}
@GetMapping("/view")
public Mono<ResponseEntity<byte[]>> viewFile(@RequestParam("path") String path) {
String contentType = "image/jpeg";
if (path.endsWith(".png")) contentType = "image/png";
else if (path.endsWith(".pdf")) contentType = "application/pdf";
else if (path.endsWith(".webp")) contentType = "image/webp";
final String finalContentType = contentType;
return minioServiceClient.downloadFile(contentType, path)
.map(response -> {
byte[] decodedBytes = Base64.getDecoder().decode(response.getBase64Content());
return ResponseEntity.ok()
.header(HttpHeaders.CONTENT_TYPE, finalContentType)
.header(HttpHeaders.CACHE_CONTROL, "max-age=86400")
.body(decodedBytes);
});
}
}

View File

@@ -0,0 +1,25 @@
package com.kifi.api.controller;
import com.kifi.api.entity.User;
import com.kifi.api.service.UserService;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Mono;
import java.util.List;
@RestController
@RequestMapping("/api/kifi-v2/users")
@RequiredArgsConstructor
public class UserController {
private final UserService userService;
@GetMapping("/search")
public Mono<ResponseEntity<List<User>>> searchUsers(@RequestParam String q) {
return userService.searchUsers(q)
.collectList()
.map(ResponseEntity::ok);
}
}

View File

@@ -13,7 +13,7 @@ import reactor.core.publisher.Mono;
import java.util.List; import java.util.List;
@RestController @RestController
@RequestMapping("/api/kifi/wallets") @RequestMapping("/api/kifi-v2/wallets")
@RequiredArgsConstructor @RequiredArgsConstructor
public class WalletController { public class WalletController {
@@ -28,13 +28,18 @@ public class WalletController {
@PostMapping @PostMapping
public Mono<Wallet> createWallet(@RequestBody CreateWalletRequest request, Authentication authentication) { public Mono<Wallet> createWallet(@RequestBody CreateWalletRequest request, Authentication authentication) {
Long userId = Long.valueOf(authentication.getDetails().toString()); Long userId = Long.valueOf(authentication.getDetails().toString());
return walletService.createWallet(userId, request.getName(), request.getNature(), request.getIcon(), request.getColor(), request.getCurrency(), request.getInitialBalance()); return walletService.createWallet(userId, request.getName(), request.getNature(), request.getIcon(), request.getColor(), request.getCurrency(), request.getInitialBalance(), request.getInitialBalanceDate(), request.getSubNature(), request.getCreditLimit(), request.getFixedAmount(), request.getPaymentCycle(), request.getCycleDate());
} }
@PutMapping("/{walletId}") @PutMapping("/{walletId}")
public Mono<Wallet> editWallet(@PathVariable Long walletId, @RequestBody CreateWalletRequest request, Authentication authentication) { public Mono<Wallet> editWallet(@PathVariable Long walletId, @RequestBody CreateWalletRequest request, Authentication authentication) {
Long userId = Long.valueOf(authentication.getDetails().toString()); Long userId = Long.valueOf(authentication.getDetails().toString());
return walletService.editWallet(walletId, userId, request.getName(), request.getNature(), request.getIcon(), request.getColor(), request.getCurrency()); return walletService.editWallet(walletId, userId, request.getName(), request.getNature(), request.getIcon(), request.getColor(), request.getCurrency(), request.getInitialBalance(), request.getInitialBalanceDate(), request.getSubNature(), request.getCreditLimit(), request.getFixedAmount(), request.getPaymentCycle(), request.getCycleDate());
}
@PutMapping("/test/{walletId}/{userId}")
public Mono<Wallet> editWalletTest(@PathVariable Long walletId, @PathVariable Long userId, @RequestBody CreateWalletRequest request) {
return walletService.editWallet(walletId, userId, request.getName(), request.getNature(), request.getIcon(), request.getColor(), request.getCurrency(), request.getInitialBalance(), request.getInitialBalanceDate(), request.getSubNature(), request.getCreditLimit(), request.getFixedAmount(), request.getPaymentCycle(), request.getCycleDate());
} }
@DeleteMapping("/{walletId}") @DeleteMapping("/{walletId}")
@@ -95,6 +100,12 @@ public class WalletController {
private String color; private String color;
private String currency; private String currency;
private java.math.BigDecimal initialBalance; private java.math.BigDecimal initialBalance;
private java.time.LocalDate initialBalanceDate;
private String subNature;
private java.math.BigDecimal creditLimit;
private java.math.BigDecimal fixedAmount;
private String paymentCycle;
private Integer cycleDate;
} }
@Data @Data

View File

@@ -0,0 +1,47 @@
package com.kifi.api.controller.business;
import com.kifi.api.entity.business.BusinessProfile;
import com.kifi.api.entity.business.BusinessFeature;
import com.kifi.api.service.business.BusinessService;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.Authentication;
import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Mono;
@RestController
@RequestMapping("/api/kifi-v2/business")
@RequiredArgsConstructor
public class BusinessController {
private final BusinessService businessService;
// TODO: Obtain user ID from auth context, using hardcoded for now or parameter
@GetMapping("/profile")
public Mono<ResponseEntity<BusinessProfile>> getProfile(Authentication authentication) {
Long userId = Long.valueOf(authentication.getDetails().toString());
return businessService.getProfileByUserId(userId)
.map(ResponseEntity::ok)
.defaultIfEmpty(ResponseEntity.notFound().build());
}
@PostMapping("/profile")
public Mono<ResponseEntity<BusinessProfile>> saveProfile(Authentication authentication, @RequestBody BusinessProfile profile) {
Long userId = Long.valueOf(authentication.getDetails().toString());
return businessService.saveProfile(userId, profile)
.map(ResponseEntity::ok);
}
@GetMapping("/features")
public Mono<ResponseEntity<BusinessFeature>> getFeatures(Authentication authentication) {
Long userId = Long.valueOf(authentication.getDetails().toString());
return businessService.getFeaturesByUserId(userId)
.map(ResponseEntity::ok);
}
@PostMapping("/features")
public Mono<ResponseEntity<BusinessFeature>> saveFeatures(Authentication authentication, @RequestBody BusinessFeature feature) {
Long userId = Long.valueOf(authentication.getDetails().toString());
return businessService.saveFeatures(userId, feature)
.map(ResponseEntity::ok);
}
}

View File

@@ -0,0 +1,21 @@
package com.kifi.api.controller.business;
import com.kifi.api.entity.business.IndianState;
import com.kifi.api.repository.business.IndianStateRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Flux;
@RestController
@RequestMapping("/api/kifi-v2/master")
@RequiredArgsConstructor
public class MasterDataController {
private final IndianStateRepository indianStateRepository;
@GetMapping("/states")
public Flux<IndianState> getIndianStates() {
return indianStateRepository.findAllByOrderByNameAsc();
}
}

View File

@@ -0,0 +1,94 @@
package com.kifi.api.controller.customer;
import com.kifi.api.entity.customer.Customer;
import com.kifi.api.service.customer.CustomerService;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.codec.multipart.FilePart;
import org.springframework.core.io.buffer.DataBufferUtils;
import org.springframework.security.core.Authentication;
import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import java.util.Base64;
@RestController
@RequestMapping("/api/kifi-v2/customers")
@RequiredArgsConstructor
public class CustomerController {
private final CustomerService customerService;
@GetMapping
public Flux<Customer> getCustomers(
Authentication authentication,
@RequestParam(required = false) String search) {
Long userId = Long.valueOf(authentication.getDetails().toString());
return customerService.getCustomers(userId, search);
}
@GetMapping("/{id}")
public Mono<Customer> getCustomerById(
@PathVariable Long id,
Authentication authentication) {
Long userId = Long.valueOf(authentication.getDetails().toString());
return customerService.getCustomerById(id, userId);
}
@PostMapping
public Mono<Customer> createCustomer(
Authentication authentication,
@RequestBody Customer customer) {
Long userId = Long.valueOf(authentication.getDetails().toString());
return customerService.createCustomer(userId, customer);
}
@PutMapping("/{id}")
public Mono<Customer> updateCustomer(
@PathVariable Long id,
Authentication authentication,
@RequestBody Customer customer) {
Long userId = Long.valueOf(authentication.getDetails().toString());
return customerService.updateCustomer(id, userId, customer);
}
@DeleteMapping("/{id}")
public Mono<Void> deleteCustomer(
@PathVariable Long id,
Authentication authentication) {
Long userId = Long.valueOf(authentication.getDetails().toString());
return customerService.deleteCustomer(id, userId);
}
@PostMapping(value = "/{id}/photo", consumes = org.springframework.http.MediaType.MULTIPART_FORM_DATA_VALUE)
public Mono<Customer> uploadPhoto(
@PathVariable Long id,
Authentication authentication,
@RequestPart("file") FilePart filePart) {
Long userId = Long.valueOf(authentication.getDetails().toString());
return DataBufferUtils.join(filePart.content())
.flatMap(dataBuffer -> {
byte[] bytes = new byte[dataBuffer.readableByteCount()];
dataBuffer.read(bytes);
DataBufferUtils.release(dataBuffer);
String base64Content = Base64.getEncoder().encodeToString(bytes);
String contentType = filePart.headers().getContentType() != null ? filePart.headers().getContentType().toString() : "image/jpeg";
return customerService.uploadPhoto(id, userId, contentType, base64Content);
});
}
@GetMapping("/{id}/photo/content")
public Mono<ResponseEntity<byte[]>> downloadPhoto(
@PathVariable Long id,
Authentication authentication) {
Long userId = Long.valueOf(authentication.getDetails().toString());
return customerService.downloadPhoto(id, userId)
.map(base64Content -> {
byte[] decodedBytes = Base64.getDecoder().decode(base64Content);
return ResponseEntity.ok()
.header(HttpHeaders.CONTENT_TYPE, "image/jpeg")
.body(decodedBytes);
});
}
}

View File

@@ -0,0 +1,66 @@
package com.kifi.api.controller.inventory;
import com.kifi.api.entity.inventory.CommodityRateHistory;
import com.kifi.api.service.inventory.CommodityRateService;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.Authentication;
import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import java.util.Map;
@RestController
@RequestMapping("/api/kifi-v2/inventory/commodity-rates")
@RequiredArgsConstructor
public class CommodityRateController {
private final CommodityRateService rateService;
@GetMapping("/latest")
public Flux<CommodityRateHistory> getAllLatestRates() {
return rateService.getAllLatestRates();
}
@GetMapping("/{commodityCode}")
public Flux<CommodityRateHistory> getRateHistory(@PathVariable String commodityCode) {
return rateService.getRateHistory(commodityCode);
}
@GetMapping("/{commodityCode}/latest")
public Mono<ResponseEntity<CommodityRateHistory>> getLatestRate(@PathVariable String commodityCode) {
return rateService.getLatestRate(commodityCode)
.map(ResponseEntity::ok)
.defaultIfEmpty(ResponseEntity.notFound().build());
}
@PostMapping
public Mono<ResponseEntity<CommodityRateHistory>> addRate(
Authentication authentication,
@RequestBody CommodityRateHistory rateHistory) {
Long userId = Long.valueOf(authentication.getDetails().toString());
String code = rateHistory.getCommodityCode() != null ? rateHistory.getCommodityCode() : rateHistory.getCommodityName();
String name = rateHistory.getCommodityName() != null ? rateHistory.getCommodityName() : code;
return rateService.addRate(
code,
name,
rateHistory.getPurity(),
rateHistory.getRate(),
rateHistory.getSource() != null ? rateHistory.getSource() : "MANUAL",
userId
).map(ResponseEntity::ok);
}
@PostMapping("/{commodityCode}/sync")
public Mono<ResponseEntity<Map<String, Object>>> syncRatesToProducts(
Authentication authentication,
@PathVariable String commodityCode) {
Long userId = Long.valueOf(authentication.getDetails().toString());
return rateService.syncRatesToProducts(commodityCode, userId)
.map(count -> ResponseEntity.ok(Map.<String, Object>of(
"commodityCode", commodityCode,
"updatedCount", count,
"message", "Successfully synced rates for " + count + " products"
)));
}
}

View File

@@ -0,0 +1,59 @@
package com.kifi.api.controller.inventory;
import com.kifi.api.entity.inventory.InventoryItem;
import com.kifi.api.service.inventory.InventoryItemService;
import com.kifi.api.service.inventory.InventoryValuationService;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.Authentication;
import java.math.BigDecimal;
import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
@RestController
@RequestMapping("/api/kifi-v2/inventory/items")
@RequiredArgsConstructor
public class InventoryItemController {
private final InventoryItemService inventoryItemService;
private final InventoryValuationService inventoryValuationService;
@GetMapping
public Flux<InventoryItem> getItems(Authentication authentication) {
Long userId = Long.valueOf(authentication.getDetails().toString());
return inventoryItemService.getItemsByUserId(userId);
}
@GetMapping("/product/{productId}")
public Flux<InventoryItem> getItemsByProductId(@PathVariable Long productId, Authentication authentication) {
Long userId = Long.valueOf(authentication.getDetails().toString());
return inventoryItemService.getItemsByProductId(userId, productId);
}
@GetMapping("/total-value")
public Mono<ResponseEntity<BigDecimal>> getTotalInventoryValue(Authentication authentication) {
Long userId = Long.valueOf(authentication.getDetails().toString());
return inventoryValuationService.calculateTotalInventoryValue(userId)
.map(ResponseEntity::ok);
}
@PostMapping
public Mono<ResponseEntity<InventoryItem>> createItem(
Authentication authentication,
@RequestBody InventoryItem item) {
Long userId = Long.valueOf(authentication.getDetails().toString());
return inventoryItemService.createItem(userId, item)
.map(ResponseEntity::ok);
}
@PutMapping("/{id}")
public Mono<ResponseEntity<InventoryItem>> updateItem(
Authentication authentication,
@PathVariable Long id,
@RequestBody InventoryItem item) {
Long userId = Long.valueOf(authentication.getDetails().toString());
return inventoryItemService.updateItem(userId, id, item)
.map(ResponseEntity::ok)
.defaultIfEmpty(ResponseEntity.notFound().build());
}
}

View File

@@ -0,0 +1,24 @@
package com.kifi.api.controller.inventory;
import com.kifi.api.dto.inventory.MovementRequestDto;
import com.kifi.api.entity.inventory.InventoryMovement;
import com.kifi.api.service.inventory.InventoryMovementService;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.Authentication;
import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Mono;
@RestController
@RequestMapping("/api/kifi-v2/inventory/movements")
@RequiredArgsConstructor
public class InventoryMovementController {
private final InventoryMovementService movementService;
@PostMapping
public Mono<ResponseEntity<InventoryMovement>> recordMovement(Authentication authentication, @RequestBody MovementRequestDto request) {
Long userId = Long.valueOf(authentication.getDetails().toString());
return movementService.recordMovement(userId, request.getMovement(), request.getItems())
.map(ResponseEntity::ok);
}
}

View File

@@ -0,0 +1,45 @@
package com.kifi.api.controller.inventory;
import com.kifi.api.entity.inventory.ProductBom;
import com.kifi.api.service.inventory.ProductService;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.Authentication;
import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
@RestController
@RequestMapping("/api/kifi-v2/inventory/products")
@RequiredArgsConstructor
public class ProductBomController {
private final ProductService productService;
@GetMapping("/{id}/bom")
public Flux<ProductBom> getProductBom(Authentication authentication, @PathVariable Long id) {
Long userId = Long.valueOf(authentication.getDetails().toString());
// Validation could be added to ensure the user owns the parent product
return productService.getProductBom(id);
}
@PostMapping("/{id}/bom")
public Mono<ResponseEntity<ProductBom>> addOrUpdateBomItem(
Authentication authentication,
@PathVariable Long id,
@RequestBody ProductBom bomItem) {
Long userId = Long.valueOf(authentication.getDetails().toString());
bomItem.setParentProductId(id);
return productService.addOrUpdateBomItem(userId, bomItem)
.map(ResponseEntity::ok);
}
@DeleteMapping("/bom/{bomId}")
public Mono<ResponseEntity<Void>> deleteBomItem(
Authentication authentication,
@PathVariable Long bomId) {
Long userId = Long.valueOf(authentication.getDetails().toString());
return productService.deleteBomItem(userId, bomId)
.then(Mono.just(ResponseEntity.noContent().<Void>build()));
}
}

View File

@@ -0,0 +1,75 @@
package com.kifi.api.controller.inventory;
import com.kifi.api.entity.inventory.ProductCategory;
import com.kifi.api.repository.inventory.ProductCategoryRepository;
// Removed CategoryRateHistory
import com.kifi.api.service.inventory.ProductService;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.Authentication;
import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.math.BigDecimal;
import java.util.Map;
@RestController
@RequestMapping("/api/kifi-v2/inventory/categories")
@RequiredArgsConstructor
public class ProductCategoryController {
private final ProductCategoryRepository categoryRepository;
private final ProductService productService;
@GetMapping
public Flux<ProductCategory> getCategories(Authentication authentication) {
Long userId = Long.valueOf(authentication.getDetails().toString());
return categoryRepository.findByUserId(userId);
}
@PostMapping
public Mono<ResponseEntity<ProductCategory>> createCategory(Authentication authentication, @RequestBody ProductCategory category) {
Long userId = Long.valueOf(authentication.getDetails().toString());
category.setUserId(userId);
category.setPurityFactor(normalizePurity(category.getPurityFactor()));
category.setCreatedAt(LocalDateTime.now());
return categoryRepository.save(category)
.map(ResponseEntity::ok);
}
@PutMapping("/{id}")
public Mono<ResponseEntity<ProductCategory>> updateCategory(@PathVariable Long id, @RequestBody ProductCategory category) {
return categoryRepository.findById(id)
.flatMap(existing -> {
existing.setName(category.getName());
existing.setParentCategoryId(category.getParentCategoryId());
existing.setHasChild(category.getHasChild());
existing.setCommodityCode(category.getCommodityCode());
existing.setPurityFactor(normalizePurity(category.getPurityFactor()));
existing.setDefaultHsn(category.getDefaultHsn());
existing.setDefaultGst(category.getDefaultGst());
existing.setHuidRequired(category.getHuidRequired());
existing.setDefaultMakingCharge(category.getDefaultMakingCharge());
existing.setMakingChargeType(category.getMakingChargeType());
existing.setBaseUnit(category.getBaseUnit());
existing.setIsActive(category.getIsActive());
existing.setSortOrder(category.getSortOrder());
return categoryRepository.save(existing);
})
.map(ResponseEntity::ok)
.defaultIfEmpty(ResponseEntity.notFound().build());
}
private Double normalizePurity(Double rawPurity) {
if (rawPurity == null || rawPurity <= 0) return 1.0;
double p = rawPurity;
if (p > 1.0) p = p / 100.0;
if (p > 1.0) p = 1.0;
return p;
}
}

View File

@@ -0,0 +1,103 @@
package com.kifi.api.controller.inventory;
import com.kifi.api.entity.inventory.Product;
import com.kifi.api.entity.inventory.ProductImage;
import com.kifi.api.service.inventory.ProductService;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.Authentication;
import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import org.springframework.http.codec.multipart.FilePart;
import org.springframework.core.io.buffer.DataBufferUtils;
import org.springframework.http.HttpHeaders;
import java.util.Base64;
@RestController
@RequestMapping("/api/kifi-v2/inventory/products")
@RequiredArgsConstructor
public class ProductController {
private final ProductService productService;
@GetMapping
public Flux<Product> getProducts(
Authentication authentication,
@RequestParam(required = false) String search,
@RequestParam(defaultValue = "0") int page,
@RequestParam(defaultValue = "20") int size
) {
Long userId = Long.valueOf(authentication.getDetails().toString());
return productService.getProductsByUserId(userId, search, page, size)
.doOnNext(p -> System.out.println("Returning product: " + p.getName() + ", currentStock: " + p.getCurrentStock()));
}
@PostMapping
public Mono<ResponseEntity<Product>> createProduct(Authentication authentication, @RequestBody Product product) {
Long userId = Long.valueOf(authentication.getDetails().toString());
return productService.createProduct(userId, product)
.map(ResponseEntity::ok);
}
@PutMapping("/{id}")
public Mono<ResponseEntity<Product>> updateProduct(
Authentication authentication,
@PathVariable Long id,
@RequestBody Product product
) {
Long userId = Long.valueOf(authentication.getDetails().toString());
return productService.updateProduct(userId, id, product)
.map(ResponseEntity::ok)
.defaultIfEmpty(ResponseEntity.notFound().build());
}
@PostMapping(value = "/{id}/images", consumes = org.springframework.http.MediaType.MULTIPART_FORM_DATA_VALUE)
public Mono<ProductImage> addImage(@PathVariable Long id, @RequestPart("file") FilePart filePart) {
return DataBufferUtils.join(filePart.content())
.flatMap(dataBuffer -> {
byte[] bytes = new byte[dataBuffer.readableByteCount()];
dataBuffer.read(bytes);
DataBufferUtils.release(dataBuffer);
String base64Content = Base64.getEncoder().encodeToString(bytes);
String fileName = filePart.filename();
String contentType = filePart.headers().getContentType() != null ? filePart.headers().getContentType().toString() : "application/octet-stream";
return productService.addProductImage(id, fileName, contentType, base64Content);
});
}
@GetMapping("/{id}/images/{imageId}/content")
public Mono<ResponseEntity<byte[]>> downloadImage(@PathVariable Long id, @PathVariable Long imageId) {
return productService.downloadProductImage(imageId)
.map(response -> {
byte[] decodedBytes = Base64.getDecoder().decode(response.getBase64Content());
return ResponseEntity.ok()
.header(HttpHeaders.CONTENT_TYPE, "image/jpeg")
.body(decodedBytes);
});
}
@DeleteMapping("/images/{imageId}")
public Mono<Void> deleteImage(@PathVariable Long imageId) {
return productService.deleteProductImage(imageId);
}
@PostMapping("/{id}/movements")
public Mono<ResponseEntity<com.kifi.api.entity.inventory.InventoryMovement>> adjustStock(
Authentication authentication,
@PathVariable Long id,
@RequestBody com.kifi.api.entity.inventory.InventoryMovement movement
) {
Long userId = Long.valueOf(authentication.getDetails().toString());
return productService.adjustStock(userId, id, movement)
.map(ResponseEntity::ok);
}
@GetMapping("/{id}/movements")
public Flux<com.kifi.api.entity.inventory.InventoryMovement> getStockLedger(
Authentication authentication,
@PathVariable Long id
) {
Long userId = Long.valueOf(authentication.getDetails().toString());
return productService.getProductStockLedger(userId, id);
}
}

View File

@@ -0,0 +1,51 @@
package com.kifi.api.controller.inventory;
import com.kifi.api.entity.inventory.UnitOfMeasure;
import com.kifi.api.service.inventory.UnitOfMeasureService;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.security.core.Authentication;
import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
@RestController
@RequestMapping("/api/kifi-v2/inventory/uom")
@RequiredArgsConstructor
public class UnitOfMeasureController {
private final UnitOfMeasureService uomService;
@GetMapping
public Flux<UnitOfMeasure> getUoms(Authentication authentication) {
Long userId = Long.valueOf(authentication.getDetails().toString());
return uomService.getUomsByUserId(userId);
}
@GetMapping("/{id}")
public Mono<UnitOfMeasure> getUomById(@PathVariable Long id, Authentication authentication) {
Long userId = Long.valueOf(authentication.getDetails().toString());
return uomService.getUomById(id, userId);
}
@PostMapping
@ResponseStatus(HttpStatus.CREATED)
public Mono<UnitOfMeasure> createUom(@RequestBody UnitOfMeasure uom, Authentication authentication) {
Long userId = Long.valueOf(authentication.getDetails().toString());
uom.setUserId(userId);
return uomService.createUom(uom);
}
@PutMapping("/{id}")
public Mono<UnitOfMeasure> updateUom(@PathVariable Long id, @RequestBody UnitOfMeasure uom, Authentication authentication) {
Long userId = Long.valueOf(authentication.getDetails().toString());
return uomService.updateUom(id, uom, userId);
}
@DeleteMapping("/{id}")
@ResponseStatus(HttpStatus.NO_CONTENT)
public Mono<Void> deleteUom(@PathVariable Long id, Authentication authentication) {
Long userId = Long.valueOf(authentication.getDetails().toString());
return uomService.deleteUom(id, userId);
}
}

View File

@@ -0,0 +1,64 @@
package com.kifi.api.controller.invoice;
import com.kifi.api.entity.invoice.Invoice;
import com.kifi.api.service.invoice.InvoiceService;
import lombok.RequiredArgsConstructor;
import org.springframework.security.core.Authentication;
import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
@RestController
@RequestMapping("/api/kifi-v2/invoices")
@RequiredArgsConstructor
public class InvoiceController {
private final InvoiceService invoiceService;
@GetMapping
public Flux<Invoice> getInvoices(Authentication authentication) {
Long userId = Long.valueOf(authentication.getDetails().toString());
return invoiceService.getInvoices(userId);
}
@GetMapping("/{id}")
public Mono<Invoice> getInvoiceById(
@PathVariable Long id,
Authentication authentication) {
Long userId = Long.valueOf(authentication.getDetails().toString());
return invoiceService.getInvoiceById(id, userId);
}
@PostMapping
public Mono<Invoice> createInvoice(
Authentication authentication,
@RequestBody Invoice invoice) {
Long userId = Long.valueOf(authentication.getDetails().toString());
return invoiceService.createInvoice(userId, invoice);
}
@PutMapping("/{id}/finalize")
public Mono<Invoice> finalizeInvoice(
@PathVariable Long id,
Authentication authentication) {
Long userId = Long.valueOf(authentication.getDetails().toString());
return invoiceService.finalizeInvoice(id, userId);
}
@PostMapping("/{id}/payments")
public Mono<com.kifi.api.entity.invoice.InvoicePayment> addPayment(
@PathVariable Long id,
Authentication authentication,
@RequestBody com.kifi.api.entity.invoice.InvoicePayment payment) {
Long userId = Long.valueOf(authentication.getDetails().toString());
return invoiceService.addPaymentToInvoice(id, userId, payment);
}
@GetMapping("/{id}/payments")
public Flux<com.kifi.api.entity.invoice.InvoicePayment> getPayments(
@PathVariable Long id,
Authentication authentication) {
Long userId = Long.valueOf(authentication.getDetails().toString());
return invoiceService.getPaymentsForInvoice(id, userId);
}
}

View File

@@ -0,0 +1,93 @@
package com.kifi.api.controller.vendor;
import com.kifi.api.entity.vendor.PurchaseOrder;
import com.kifi.api.entity.vendor.PurchaseOrderItem;
import com.kifi.api.entity.vendor.PurchasePayment;
import com.kifi.api.service.vendor.PurchaseOrderService;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.Authentication;
import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import java.util.List;
@RestController
@RequestMapping("/api/kifi-v2/purchase-orders")
@RequiredArgsConstructor
public class PurchaseOrderController {
private final PurchaseOrderService purchaseOrderService;
@GetMapping
public Mono<ResponseEntity<Flux<PurchaseOrder>>> getPurchaseOrders(Authentication authentication) {
Long userId = Long.valueOf(authentication.getDetails().toString());
return Mono.just(ResponseEntity.ok(purchaseOrderService.getPurchaseOrders(userId)));
}
@GetMapping("/test/{id}")
public Mono<ResponseEntity<PurchaseOrder>> testGet(@PathVariable Long id) {
return purchaseOrderService.getPurchaseOrder(1L, id)
.flatMap(po -> purchaseOrderService.getPurchaseOrderItems(id)
.collectList()
.map(items -> {
po.setItems(items);
return ResponseEntity.ok(po);
}));
}
@GetMapping("/{id}")
public Mono<ResponseEntity<PurchaseOrder>> getPurchaseOrder(@PathVariable Long id, Authentication authentication) {
Long userId = Long.valueOf(authentication.getDetails().toString());
return purchaseOrderService.getPurchaseOrder(userId, id)
.flatMap(po -> purchaseOrderService.getPurchaseOrderItems(id)
.collectList()
.map(items -> {
System.out.println("Fetched PO ID " + id + ", Items count: " + items.size());
po.setItems(items);
return ResponseEntity.ok(po);
}))
.defaultIfEmpty(ResponseEntity.notFound().build());
}
@PostMapping
public Mono<ResponseEntity<PurchaseOrder>> createPurchaseOrder(Authentication authentication, @RequestBody PurchaseOrder po) {
Long userId = Long.valueOf(authentication.getDetails().toString());
System.out.println("---- CREATE PO RECEIVED ITEMS ----");
System.out.println(po.getItems());
return purchaseOrderService.createPurchaseOrder(userId, po, po.getItems())
.map(ResponseEntity::ok);
}
@PutMapping("/{id}")
public Mono<ResponseEntity<PurchaseOrder>> updatePurchaseOrder(@PathVariable Long id, Authentication authentication, @RequestBody PurchaseOrder po) {
Long userId = Long.valueOf(authentication.getDetails().toString());
return purchaseOrderService.updatePurchaseOrder(userId, id, po, po.getItems())
.map(ResponseEntity::ok)
.defaultIfEmpty(ResponseEntity.notFound().build());
}
@PutMapping("/{id}/receive")
public Mono<ResponseEntity<PurchaseOrder>> markAsReceived(@PathVariable Long id, Authentication authentication, @RequestBody(required = false) PurchaseOrder po) {
Long userId = Long.valueOf(authentication.getDetails().toString());
List<PurchaseOrderItem> items = (po != null) ? po.getItems() : null;
return purchaseOrderService.markAsReceived(userId, id, items)
.map(ResponseEntity::ok);
}
@PostMapping("/{id}/payments")
public Mono<ResponseEntity<PurchasePayment>> addPayment(@PathVariable Long id, Authentication authentication, @RequestBody PurchasePayment payment) {
Long userId = Long.valueOf(authentication.getDetails().toString());
return purchaseOrderService.addPayment(userId, id, payment)
.map(ResponseEntity::ok)
.onErrorResume(e -> Mono.just(ResponseEntity.badRequest().build()));
}
@GetMapping("/{id}/payments")
public Mono<ResponseEntity<List<PurchasePayment>>> getPayments(@PathVariable Long id, Authentication authentication) {
Long userId = Long.valueOf(authentication.getDetails().toString());
return purchaseOrderService.getPayments(userId, id)
.collectList()
.map(ResponseEntity::ok);
}
}

View File

@@ -0,0 +1,51 @@
package com.kifi.api.controller.vendor;
import com.kifi.api.entity.vendor.Vendor;
import com.kifi.api.service.vendor.VendorService;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.Authentication;
import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
@RestController
@RequestMapping("/api/kifi-v2/vendors")
@RequiredArgsConstructor
public class VendorController {
private final VendorService vendorService;
@GetMapping
public Mono<ResponseEntity<Flux<Vendor>>> getVendors(Authentication authentication) {
Long userId = Long.valueOf(authentication.getDetails().toString());
return Mono.just(ResponseEntity.ok(vendorService.getVendors(userId)));
}
@GetMapping("/{id}")
public Mono<ResponseEntity<Vendor>> getVendor(@PathVariable Long id) {
return vendorService.getVendor(id)
.map(ResponseEntity::ok)
.defaultIfEmpty(ResponseEntity.notFound().build());
}
@PostMapping
public Mono<ResponseEntity<Vendor>> createVendor(Authentication authentication, @RequestBody Vendor vendor) {
Long userId = Long.valueOf(authentication.getDetails().toString());
return vendorService.createVendor(userId, vendor)
.map(ResponseEntity::ok);
}
@PutMapping("/{id}")
public Mono<ResponseEntity<Vendor>> updateVendor(@PathVariable Long id, @RequestBody Vendor vendor) {
return vendorService.updateVendor(id, vendor)
.map(ResponseEntity::ok)
.defaultIfEmpty(ResponseEntity.notFound().build());
}
@DeleteMapping("/{id}")
public Mono<ResponseEntity<Void>> deleteVendor(@PathVariable Long id) {
return vendorService.deleteVendor(id)
.then(Mono.just(ResponseEntity.ok().<Void>build()));
}
}

View File

@@ -0,0 +1,23 @@
package com.kifi.api.dto;
import lombok.Data;
@Data
public class SetupRequestDTO {
private String accountType;
private String name;
private String username;
private String mobileNumber;
private String natureOfBusiness;
private String businessName;
private String address;
private Long stateId;
private String emailId;
private String gstin;
private String panNumber;
private String msmeNumber;
private Boolean termsAccepted;
private Boolean privacyAccepted;
}

View File

@@ -0,0 +1,13 @@
package com.kifi.api.dto.inventory;
import com.kifi.api.entity.inventory.InventoryMovement;
import com.kifi.api.entity.inventory.InventoryMovementItem;
import lombok.Data;
import java.util.List;
@Data
public class MovementRequestDto {
private InventoryMovement movement;
private List<InventoryMovementItem> items;
}

View File

@@ -21,6 +21,14 @@ public class User {
private String password; private String password;
@Builder.Default @Builder.Default
private Boolean enabled = false; private Boolean enabled = false;
@Builder.Default
private String profileType = "INDIVIDUAL";
private String username;
private String name;
private String mobileNumber;
@Builder.Default
private String setupStatus = "NOT_STARTED";
private LocalDateTime setupCompletedAt;
private LocalDateTime createdAt; private LocalDateTime createdAt;
private LocalDateTime updatedAt; private LocalDateTime updatedAt;
} }

View File

@@ -0,0 +1,31 @@
package com.kifi.api.entity;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.data.annotation.Id;
import org.springframework.data.relational.core.mapping.Table;
import java.time.LocalDateTime;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Table("user_consents")
public class UserConsent {
@Id
private Long id;
private Long userId;
private String consentType;
private String policyVersion;
@Builder.Default
private Boolean accepted = true;
private LocalDateTime acceptedAt;
@org.springframework.data.relational.core.mapping.Column("ip_address")
private String ipAddress;
@org.springframework.data.relational.core.mapping.Column("user_agent")
private String userAgent;
private LocalDateTime createdAt;
}

View File

@@ -18,5 +18,10 @@ public class Wallet {
private String currency; private String currency;
private String icon; private String icon;
private String color; private String color;
private String subNature;
private java.math.BigDecimal creditLimit;
private java.math.BigDecimal fixedAmount;
private String paymentCycle;
private Integer cycleDate;
private LocalDateTime createdAt; private LocalDateTime createdAt;
} }

View File

@@ -0,0 +1,38 @@
package com.kifi.api.entity.business;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.data.annotation.Id;
import org.springframework.data.relational.core.mapping.Column;
import org.springframework.data.relational.core.mapping.Table;
import java.time.LocalDateTime;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Table("business_features")
public class BusinessFeature {
@Id
private Long id;
private Long userId;
private Boolean inventoryManagement;
private Boolean salesManagement;
private Boolean purchaseManagement;
private Boolean multiLocation;
@Column("bom_reduction_strategy")
private String bomReductionStrategy; // "COMPONENTS_ONLY" or "PARENT_AND_COMPONENTS"
@Column("stock_deduction_on_invoice")
private Boolean stockDeductionOnInvoice;
@Column("barcode_source")
private String barcodeSource;
@Column("created_at")
private LocalDateTime createdAt;
}

View File

@@ -0,0 +1,37 @@
package com.kifi.api.entity.business;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.data.annotation.Id;
import org.springframework.data.relational.core.mapping.Table;
import java.time.LocalDateTime;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Table("business_profiles")
public class BusinessProfile {
@Id
private Long id;
private Long userId;
private String businessName;
private String industry;
private String taxNumber;
private String currency;
private Boolean taxIncludedInPrice;
private String address;
private Long stateId;
private String contactPerson;
private String contactNumber;
private String emailId;
private String panNumber;
private String gstin;
private String natureOfBusiness;
private String msmeNumber;
private LocalDateTime createdAt;
private LocalDateTime updatedAt;
}

View File

@@ -0,0 +1,20 @@
package com.kifi.api.entity.business;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.data.annotation.Id;
import org.springframework.data.relational.core.mapping.Table;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Table("indian_states")
public class IndianState {
@Id
private Long id;
private String name;
private String gstCode;
}

View File

@@ -0,0 +1,48 @@
package com.kifi.api.entity.customer;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.data.annotation.Id;
import org.springframework.data.relational.core.mapping.Column;
import org.springframework.data.relational.core.mapping.Table;
import java.time.LocalDateTime;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Table("customers")
public class Customer {
@Id
private Long id;
@Column("user_id")
private Long userId;
private String name;
private String email;
private String phone;
private String address;
private String gstin;
@Column("father_name")
private String fatherName;
private String gender;
private Integer age;
@Column("id_number")
private String idNumber;
@Column("state_id")
private Integer stateId;
@Column("photo_url")
private String photoUrl;
@Column("created_at")
private LocalDateTime createdAt;
}

View File

@@ -0,0 +1,29 @@
package com.kifi.api.entity.inventory;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.data.annotation.Id;
import org.springframework.data.relational.core.mapping.Table;
import java.math.BigDecimal;
import java.time.LocalDateTime;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Table("commodity_rate_history")
public class CommodityRateHistory {
@Id
private Long id;
private String commodityCode;
private String commodityName;
private String purity;
private BigDecimal rate;
private LocalDateTime effectiveAt;
private String source;
private Long createdBy;
private LocalDateTime createdAt;
}

View File

@@ -0,0 +1,25 @@
package com.kifi.api.entity.inventory;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.data.annotation.Id;
import org.springframework.data.relational.core.mapping.Table;
import java.math.BigDecimal;
import java.time.LocalDateTime;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Table("inventory_balances")
public class InventoryBalance {
@Id
private Long id;
private Long productId;
private Long locationId;
private BigDecimal quantity;
private LocalDateTime lastUpdated;
}

View File

@@ -0,0 +1,46 @@
package com.kifi.api.entity.inventory;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.data.annotation.Id;
import org.springframework.data.relational.core.mapping.Table;
import java.math.BigDecimal;
import java.time.LocalDateTime;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Table("inventory_items")
public class InventoryItem {
@Id
private Long id;
private Long userId;
private Long productId;
private String tagNumber;
private String sku;
private String huid;
private String purity;
private BigDecimal grossWeight;
private BigDecimal netWeight;
private BigDecimal stoneWeight;
private BigDecimal diamondWeight;
private BigDecimal fineWeight;
private BigDecimal makingCharges;
private String makingChargeType;
private BigDecimal purchaseCost;
private BigDecimal metalCost;
private BigDecimal stoneCost;
private BigDecimal certificationCost;
private BigDecimal tax;
private Long vendorId;
private Long branchId;
private String purchaseRef;
@Builder.Default
private String status = "AVAILABLE";
private LocalDateTime createdAt;
private LocalDateTime updatedAt;
}

View File

@@ -0,0 +1,25 @@
package com.kifi.api.entity.inventory;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.data.annotation.Id;
import org.springframework.data.relational.core.mapping.Table;
import java.time.LocalDateTime;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Table("inventory_locations")
public class InventoryLocation {
@Id
private Long id;
private Long userId;
private String name;
private String address;
private Boolean isPrimary;
private LocalDateTime createdAt;
}

View File

@@ -0,0 +1,29 @@
package com.kifi.api.entity.inventory;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.data.annotation.Id;
import org.springframework.data.relational.core.mapping.Table;
import java.time.LocalDateTime;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Table("inventory_movements")
public class InventoryMovement {
@Id
private Long id;
private Long userId;
private Long locationId;
private String type;
private Long referenceTransactionId;
private String notes;
private LocalDateTime createdAt;
@org.springframework.data.annotation.Transient
private java.util.List<InventoryMovementItem> items;
}

View File

@@ -0,0 +1,30 @@
package com.kifi.api.entity.inventory;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.data.annotation.Id;
import org.springframework.data.relational.core.mapping.Table;
import java.math.BigDecimal;
import java.time.LocalDateTime;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Table("inventory_movement_items")
public class InventoryMovementItem {
@Id
private Long id;
private Long movementId;
private Long productId;
private BigDecimal quantity;
private BigDecimal unitPrice;
private LocalDateTime createdAt;
private String huid;
private BigDecimal weight;
private String photoUrl;
private BigDecimal purchaseAmount;
}

View File

@@ -0,0 +1,50 @@
package com.kifi.api.entity.inventory;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.data.annotation.Id;
import org.springframework.data.relational.core.mapping.Table;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;
import org.springframework.data.annotation.Transient;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Table("products")
public class Product {
@Id
private Long id;
private Long userId;
private Long categoryId;
private Long uomId;
private String name;
private String sku;
private String barcode;
private String hsnCode;
private String description;
private BigDecimal sellingPrice;
private BigDecimal gstRate;
private String dimensions;
private String color;
private String size;
private String priceCalcRule;
private Double purityFactor;
private Double makingCharges;
private String makingChargesType;
private Double wastagePercentage;
private Boolean isActive;
private LocalDateTime createdAt;
private LocalDateTime updatedAt;
@Transient
private List<ProductImage> images;
@Transient
private BigDecimal currentStock;
}

View File

@@ -0,0 +1,25 @@
package com.kifi.api.entity.inventory;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.data.annotation.Id;
import org.springframework.data.relational.core.mapping.Table;
import java.math.BigDecimal;
import java.time.LocalDateTime;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Table("product_bom")
public class ProductBom {
@Id
private Long id;
private Long parentProductId;
private Long componentProductId;
private BigDecimal quantity;
private LocalDateTime createdAt;
}

View File

@@ -0,0 +1,44 @@
package com.kifi.api.entity.inventory;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.data.annotation.Id;
import org.springframework.data.relational.core.mapping.Column;
import org.springframework.data.relational.core.mapping.Table;
import java.time.LocalDateTime;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Table("product_categories")
public class ProductCategory {
@Id
private Long id;
private Long userId;
private String name;
private Long parentCategoryId;
@Builder.Default
private Boolean hasChild = false;
private String commodityCode;
@Builder.Default
private Double purityFactor = 1.0;
private String defaultHsn;
private java.math.BigDecimal defaultGst;
@Builder.Default
private Boolean huidRequired = false;
private Double defaultMakingCharge;
private String makingChargeType;
private String baseUnit;
@Builder.Default
private Boolean isActive = true;
@Builder.Default
private Integer sortOrder = 0;
private LocalDateTime createdAt;
}

View File

@@ -0,0 +1,25 @@
package com.kifi.api.entity.inventory;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.data.annotation.Id;
import org.springframework.data.relational.core.mapping.Table;
import java.time.LocalDateTime;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Table("product_images")
public class ProductImage {
@Id
private Long id;
private Long productId;
private String fileName;
private String filePath;
private String contentType;
private LocalDateTime createdAt;
}

View File

@@ -0,0 +1,24 @@
package com.kifi.api.entity.inventory;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.data.annotation.Id;
import org.springframework.data.relational.core.mapping.Table;
import java.time.LocalDateTime;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Table("units_of_measure")
public class UnitOfMeasure {
@Id
private Long id;
private Long userId;
private String name;
private String abbreviation;
private LocalDateTime createdAt;
}

View File

@@ -0,0 +1,100 @@
package com.kifi.api.entity.invoice;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.data.annotation.Id;
import org.springframework.data.annotation.Transient;
import org.springframework.data.relational.core.mapping.Column;
import org.springframework.data.relational.core.mapping.Table;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Table("invoices")
public class Invoice {
@Id
private Long id;
@Column("user_id")
private Long userId;
@Column("customer_id")
private Long customerId;
@Column("invoice_number")
private String invoiceNumber;
@Column("issue_date")
private LocalDate issueDate;
@Column("due_date")
private LocalDate dueDate;
private BigDecimal subtotal;
@Column("tax_total")
private BigDecimal taxTotal;
@Column("cgst_total")
private BigDecimal cgstTotal;
@Column("sgst_total")
private BigDecimal sgstTotal;
@Column("igst_total")
private BigDecimal igstTotal;
@Column("discount_total")
private BigDecimal discountTotal;
@Column("total_amount")
private BigDecimal totalAmount;
private String status; // DRAFT, SENT, PAID, PARTIAL, OVERDUE, CANCELLED
private String notes;
@Column("amount_paid")
private BigDecimal amountPaid;
@Column("next_payment_date")
private LocalDate nextPaymentDate;
// EMI fields
@Column("is_emi")
private Boolean isEmi;
@Column("emi_amount")
private BigDecimal emiAmount;
@Column("emi_cycle")
private String emiCycle; // MONTHLY, WEEKLY
@Column("emi_start_date")
private LocalDate emiStartDate;
@Column("created_at")
private LocalDateTime createdAt;
@Column("updated_at")
private LocalDateTime updatedAt;
@Transient
private List<InvoiceItem> items;
@Transient
private String paymentMethod;
@Transient
private Long paymentWalletId;
@Transient
private List<InvoicePayment> payments;
}

View File

@@ -0,0 +1,65 @@
package com.kifi.api.entity.invoice;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.data.annotation.Id;
import org.springframework.data.relational.core.mapping.Column;
import org.springframework.data.relational.core.mapping.Table;
import java.math.BigDecimal;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Table("invoice_items")
public class InvoiceItem {
@Id
private Long id;
@Column("invoice_id")
private Long invoiceId;
@Column("product_id")
private Long productId;
@Column("inventory_item_id")
private Long inventoryItemId;
@Column("hsn_code")
private String hsnCode;
private String description;
private BigDecimal quantity;
@Column("unit_price")
private BigDecimal unitPrice;
@Column("tax_rate")
private BigDecimal taxRate;
private BigDecimal discount;
@Column("making_charge")
private BigDecimal makingCharge;
@Column("making_charges_type")
private String makingChargesType;
@Column("other_charges")
private BigDecimal otherCharges;
private String huid;
private BigDecimal weight;
private BigDecimal cgst;
private BigDecimal sgst;
private BigDecimal igst;
@Column("photo_url")
private String photoUrl;
private BigDecimal total;
}

View File

@@ -0,0 +1,46 @@
package com.kifi.api.entity.invoice;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.data.annotation.Id;
import org.springframework.data.relational.core.mapping.Column;
import org.springframework.data.relational.core.mapping.Table;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Table("invoice_payments")
public class InvoicePayment {
@Id
private Long id;
@Column("invoice_id")
private Long invoiceId;
@Column("transaction_id")
private Long transactionId;
@Column("wallet_id")
private Long walletId;
private BigDecimal amount;
@Column("payment_date")
private LocalDate paymentDate;
@Column("emi_installment_number")
private Integer emiInstallmentNumber;
@Column("payment_method")
private String paymentMethod;
@Column("created_at")
private LocalDateTime createdAt;
}

View File

@@ -0,0 +1,20 @@
package com.kifi.api.entity.project;
import lombok.Data;
import org.springframework.data.annotation.Id;
import org.springframework.data.relational.core.mapping.Table;
import java.time.LocalDateTime;
@Data
@Table("projects")
public class Project {
@Id
private Long id;
private String name;
private String description;
private Long customerId;
private Long userId;
private java.math.BigDecimal budget;
private String status;
private LocalDateTime createdAt;
}

View File

@@ -0,0 +1,23 @@
package com.kifi.api.entity.project;
import lombok.Data;
import org.springframework.data.annotation.Id;
import org.springframework.data.relational.core.mapping.Table;
import java.time.LocalDateTime;
@Data
@Table("project_tasks")
public class ProjectTask {
@Id
private Long id;
private Long projectId;
private String title;
private String description;
private String assigneeName;
private Long assigneeUserId;
private String status;
private Boolean isBillable;
private java.math.BigDecimal hourlyRate;
private java.math.BigDecimal hoursLogged;
private LocalDateTime createdAt;
}

View File

@@ -0,0 +1,18 @@
package com.kifi.api.entity.project;
import lombok.Data;
import org.springframework.data.annotation.Id;
import org.springframework.data.relational.core.mapping.Table;
import java.time.LocalDateTime;
@Data
@Table("project_task_comments")
public class ProjectTaskComment {
@Id
private Long id;
private Long taskId;
private Long userId;
private String content;
private String images;
private LocalDateTime createdAt;
}

View File

@@ -0,0 +1,59 @@
package com.kifi.api.entity.vendor;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.data.annotation.Id;
import org.springframework.data.relational.core.mapping.Table;
import org.springframework.data.relational.core.mapping.Column;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;
import org.springframework.data.annotation.Transient;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Table("purchase_orders")
public class PurchaseOrder {
@Id
private Long id;
private Long userId;
private Long vendorId;
private String poNumber;
private LocalDate issueDate;
private LocalDate dueDate;
private BigDecimal subtotal;
private BigDecimal taxTotal;
private BigDecimal cgstTotal;
private BigDecimal sgstTotal;
private BigDecimal igstTotal;
private BigDecimal discountTotal;
private BigDecimal totalAmount;
private String status; // DRAFT, RECEIVED, CANCELLED
private String notes;
private LocalDateTime createdAt;
private LocalDateTime updatedAt;
private LocalDate poDate;
private BigDecimal amountPaid;
private LocalDate nextPaymentDate;
private String vendorInvoiceUrl;
@Transient
@com.fasterxml.jackson.annotation.JsonProperty(value = "items", access = com.fasterxml.jackson.annotation.JsonProperty.Access.READ_WRITE)
private List<PurchaseOrderItem> items;
@com.fasterxml.jackson.annotation.JsonProperty("items")
public List<PurchaseOrderItem> getItems() {
return items;
}
@com.fasterxml.jackson.annotation.JsonProperty("items")
public void setItems(List<PurchaseOrderItem> items) {
this.items = items;
}
}

View File

@@ -0,0 +1,37 @@
package com.kifi.api.entity.vendor;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.data.annotation.Id;
import org.springframework.data.relational.core.mapping.Table;
import java.math.BigDecimal;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Table("purchase_order_items")
public class PurchaseOrderItem {
@Id
private Long id;
private Long poId;
private Long productId;
private BigDecimal quantity;
private BigDecimal unitPrice;
private BigDecimal taxRate;
private BigDecimal cgstRate;
private BigDecimal sgstRate;
private BigDecimal igstRate;
private BigDecimal discount;
private BigDecimal total;
private String description;
private BigDecimal makingCharge;
private BigDecimal otherCharges;
private String sku;
private String huid;
private BigDecimal weight;
private String photoUrl;
}

View File

@@ -0,0 +1,27 @@
package com.kifi.api.entity.vendor;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.data.annotation.Id;
import org.springframework.data.relational.core.mapping.Table;
import java.math.BigDecimal;
import java.time.LocalDateTime;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Table("purchase_payments")
public class PurchasePayment {
@Id
private Long id;
private Long poId;
private Long transactionId;
private BigDecimal amount;
private String paymentMethod;
private LocalDateTime paymentDate;
private String notes;
}

View File

@@ -0,0 +1,31 @@
package com.kifi.api.entity.vendor;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.data.annotation.Id;
import org.springframework.data.relational.core.mapping.Table;
import java.time.LocalDateTime;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Table("vendors")
public class Vendor {
@Id
private Long id;
private Long userId;
private String name;
private String email;
private String phone;
private String address;
private String gstin;
private Long stateId;
private String idNumber;
private String photoUrl;
private String contactPerson;
private LocalDateTime createdAt;
}

View File

@@ -0,0 +1,9 @@
package com.kifi.api.repository;
import com.kifi.api.entity.project.Project;
import org.springframework.data.repository.reactive.ReactiveCrudRepository;
import reactor.core.publisher.Flux;
public interface ProjectRepository extends ReactiveCrudRepository<Project, Long> {
Flux<Project> findByUserId(Long userId);
}

View File

@@ -0,0 +1,9 @@
package com.kifi.api.repository;
import com.kifi.api.entity.project.ProjectTaskComment;
import org.springframework.data.repository.reactive.ReactiveCrudRepository;
import reactor.core.publisher.Flux;
public interface ProjectTaskCommentRepository extends ReactiveCrudRepository<ProjectTaskComment, Long> {
Flux<ProjectTaskComment> findByTaskIdOrderByCreatedAtAsc(Long taskId);
}

View File

@@ -0,0 +1,9 @@
package com.kifi.api.repository;
import com.kifi.api.entity.project.ProjectTask;
import org.springframework.data.repository.reactive.ReactiveCrudRepository;
import reactor.core.publisher.Flux;
public interface ProjectTaskRepository extends ReactiveCrudRepository<ProjectTask, Long> {
Flux<ProjectTask> findByProjectId(Long projectId);
}

View File

@@ -4,8 +4,10 @@ import com.kifi.api.entity.TransactionItem;
import org.springframework.data.repository.reactive.ReactiveCrudRepository; import org.springframework.data.repository.reactive.ReactiveCrudRepository;
import org.springframework.stereotype.Repository; import org.springframework.stereotype.Repository;
import reactor.core.publisher.Flux; import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
@Repository @Repository
public interface TransactionItemRepository extends ReactiveCrudRepository<TransactionItem, Long> { public interface TransactionItemRepository extends ReactiveCrudRepository<TransactionItem, Long> {
Flux<TransactionItem> findByTransactionId(Long transactionId); Flux<TransactionItem> findByTransactionId(Long transactionId);
Mono<Void> deleteByTransactionId(Long transactionId);
} }

View File

@@ -8,7 +8,10 @@ import reactor.core.publisher.Mono;
@Repository @Repository
public interface TransactionRepository extends R2dbcRepository<Transaction, Long>, TransactionRepositoryCustom { public interface TransactionRepository extends R2dbcRepository<Transaction, Long>, TransactionRepositoryCustom {
@org.springframework.data.r2dbc.repository.Query("SELECT t.* FROM transactions t WHERE t.user_id = :userId OR t.from_wallet_id IN (SELECT uw.wallet_id FROM user_wallets uw WHERE uw.user_id = :userId) OR t.to_wallet_id IN (SELECT uw.wallet_id FROM user_wallets uw WHERE uw.user_id = :userId) ORDER BY t.date DESC") @org.springframework.data.r2dbc.repository.Query("SELECT t.* FROM transactions t WHERE t.user_id = :userId OR t.from_wallet_id IN (SELECT uw.wallet_id FROM user_wallets uw WHERE uw.user_id = :userId) OR t.to_wallet_id IN (SELECT uw.wallet_id FROM user_wallets uw WHERE uw.user_id = :userId) ORDER BY t.date DESC, t.id DESC")
Flux<Transaction> findVisibleTransactionsForUser(Long userId); Flux<Transaction> findVisibleTransactionsForUser(Long userId);
Mono<Long> countByFromWalletIdOrToWalletId(Long fromWalletId, Long toWalletId); Mono<Long> countByFromWalletIdOrToWalletId(Long fromWalletId, Long toWalletId);
@org.springframework.data.r2dbc.repository.Query("SELECT * FROM transactions WHERE description = :description AND (from_wallet_id = :walletId OR to_wallet_id = :walletId)")
Flux<Transaction> findByWalletAndDescription(Long walletId, String description);
} }

View File

@@ -53,7 +53,7 @@ public class TransactionRepositoryImpl implements TransactionRepositoryCustom {
baseQuery.append(" AND t.description ILIKE :search"); baseQuery.append(" AND t.description ILIKE :search");
} }
String dataQueryStr = "SELECT t.* " + baseQuery.toString() + " ORDER BY t.date DESC LIMIT " + pageable.getPageSize() + " OFFSET " + pageable.getOffset(); String dataQueryStr = "SELECT t.* " + baseQuery.toString() + " ORDER BY t.date DESC, t.id DESC LIMIT " + pageable.getPageSize() + " OFFSET " + pageable.getOffset();
String countQueryStr = "SELECT COUNT(t.id) " + baseQuery.toString(); String countQueryStr = "SELECT COUNT(t.id) " + baseQuery.toString();
DatabaseClient.GenericExecuteSpec dataSpec = databaseClient.sql(dataQueryStr).bind("userId", userId); DatabaseClient.GenericExecuteSpec dataSpec = databaseClient.sql(dataQueryStr).bind("userId", userId);

View File

@@ -0,0 +1,9 @@
package com.kifi.api.repository;
import com.kifi.api.entity.UserConsent;
import org.springframework.data.repository.reactive.ReactiveCrudRepository;
import reactor.core.publisher.Mono;
public interface UserConsentRepository extends ReactiveCrudRepository<UserConsent, Long> {
Mono<UserConsent> findByUserIdAndConsentTypeAndPolicyVersion(Long userId, String consentType, String policyVersion);
}

View File

@@ -10,4 +10,8 @@ import reactor.core.publisher.Mono;
@Repository @Repository
public interface UserRepository extends R2dbcRepository<User, Long> { public interface UserRepository extends R2dbcRepository<User, Long> {
Mono<User> findByEmail(String email); Mono<User> findByEmail(String email);
Flux<User> findByEmailContainingIgnoreCase(String email);
Mono<User> findByUsername(String username);
Mono<User> findByEmailOrUsername(String email, String username);
} }

View File

@@ -6,4 +6,5 @@ import reactor.core.publisher.Flux;
public interface WalletRepository extends ReactiveCrudRepository<Wallet, Long> { public interface WalletRepository extends ReactiveCrudRepository<Wallet, Long> {
Flux<Wallet> findByOwnerId(Long ownerId); Flux<Wallet> findByOwnerId(Long ownerId);
Flux<Wallet> findByOwnerIdAndNature(Long ownerId, String nature);
} }

View File

@@ -0,0 +1,9 @@
package com.kifi.api.repository.business;
import com.kifi.api.entity.business.BusinessFeature;
import org.springframework.data.repository.reactive.ReactiveCrudRepository;
import reactor.core.publisher.Mono;
public interface BusinessFeatureRepository extends ReactiveCrudRepository<BusinessFeature, Long> {
Mono<BusinessFeature> findByUserId(Long userId);
}

View File

@@ -0,0 +1,9 @@
package com.kifi.api.repository.business;
import com.kifi.api.entity.business.BusinessProfile;
import org.springframework.data.repository.reactive.ReactiveCrudRepository;
import reactor.core.publisher.Mono;
public interface BusinessProfileRepository extends ReactiveCrudRepository<BusinessProfile, Long> {
Mono<BusinessProfile> findByUserId(Long userId);
}

View File

@@ -0,0 +1,11 @@
package com.kifi.api.repository.business;
import com.kifi.api.entity.business.IndianState;
import org.springframework.data.repository.reactive.ReactiveCrudRepository;
import org.springframework.stereotype.Repository;
import reactor.core.publisher.Flux;
@Repository
public interface IndianStateRepository extends ReactiveCrudRepository<IndianState, Long> {
Flux<IndianState> findAllByOrderByNameAsc();
}

View File

@@ -0,0 +1,10 @@
package com.kifi.api.repository.customer;
import com.kifi.api.entity.customer.Customer;
import org.springframework.data.repository.reactive.ReactiveCrudRepository;
import reactor.core.publisher.Flux;
public interface CustomerRepository extends ReactiveCrudRepository<Customer, Long> {
Flux<Customer> findByUserId(Long userId);
Flux<Customer> findByUserIdAndNameContainingIgnoreCase(Long userId, String name);
}

View File

@@ -0,0 +1,15 @@
package com.kifi.api.repository.inventory;
import com.kifi.api.entity.inventory.CommodityRateHistory;
import org.springframework.data.r2dbc.repository.Query;
import org.springframework.data.repository.reactive.ReactiveCrudRepository;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
public interface CommodityRateHistoryRepository extends ReactiveCrudRepository<CommodityRateHistory, Long> {
Flux<CommodityRateHistory> findByCommodityCodeOrderByEffectiveAtDesc(String commodityCode);
Flux<CommodityRateHistory> findByCommodityNameOrderByEffectiveAtDesc(String commodityName);
@Query("SELECT DISTINCT ON (commodity_code) * FROM commodity_rate_history WHERE commodity_code IS NOT NULL ORDER BY commodity_code, effective_at DESC")
Flux<CommodityRateHistory> findLatestRatesForAllCommodities();
}

View File

@@ -0,0 +1,12 @@
package com.kifi.api.repository.inventory;
import com.kifi.api.entity.inventory.InventoryBalance;
import org.springframework.data.repository.reactive.ReactiveCrudRepository;
import reactor.core.publisher.Mono;
import reactor.core.publisher.Flux;
public interface InventoryBalanceRepository extends ReactiveCrudRepository<InventoryBalance, Long> {
Mono<InventoryBalance> findByProductIdAndLocationId(Long productId, Long locationId);
Flux<InventoryBalance> findByLocationId(Long locationId);
Flux<InventoryBalance> findByProductId(Long productId);
}

View File

@@ -0,0 +1,14 @@
package com.kifi.api.repository.inventory;
import com.kifi.api.entity.inventory.InventoryItem;
import org.springframework.data.repository.reactive.ReactiveCrudRepository;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
public interface InventoryItemRepository extends ReactiveCrudRepository<InventoryItem, Long> {
Flux<InventoryItem> findByUserId(Long userId);
Flux<InventoryItem> findByUserIdAndProductId(Long userId, Long productId);
Flux<InventoryItem> findByProductId(Long productId);
Mono<InventoryItem> findByTagNumber(String tagNumber);
Mono<InventoryItem> findByHuid(String huid);
}

View File

@@ -0,0 +1,9 @@
package com.kifi.api.repository.inventory;
import com.kifi.api.entity.inventory.InventoryLocation;
import org.springframework.data.repository.reactive.ReactiveCrudRepository;
import reactor.core.publisher.Flux;
public interface InventoryLocationRepository extends ReactiveCrudRepository<InventoryLocation, Long> {
Flux<InventoryLocation> findByUserId(Long userId);
}

View File

@@ -0,0 +1,9 @@
package com.kifi.api.repository.inventory;
import com.kifi.api.entity.inventory.InventoryMovementItem;
import org.springframework.data.repository.reactive.ReactiveCrudRepository;
import reactor.core.publisher.Flux;
public interface InventoryMovementItemRepository extends ReactiveCrudRepository<InventoryMovementItem, Long> {
Flux<InventoryMovementItem> findByMovementId(Long movementId);
}

View File

@@ -0,0 +1,9 @@
package com.kifi.api.repository.inventory;
import com.kifi.api.entity.inventory.InventoryMovement;
import org.springframework.data.repository.reactive.ReactiveCrudRepository;
import reactor.core.publisher.Flux;
public interface InventoryMovementRepository extends ReactiveCrudRepository<InventoryMovement, Long> {
Flux<InventoryMovement> findByUserId(Long userId);
}

View File

@@ -0,0 +1,9 @@
package com.kifi.api.repository.inventory;
import com.kifi.api.entity.inventory.ProductBom;
import org.springframework.data.repository.reactive.ReactiveCrudRepository;
import reactor.core.publisher.Flux;
public interface ProductBomRepository extends ReactiveCrudRepository<ProductBom, Long> {
Flux<ProductBom> findByParentProductId(Long parentProductId);
}

View File

@@ -0,0 +1,10 @@
package com.kifi.api.repository.inventory;
import com.kifi.api.entity.inventory.ProductCategory;
import org.springframework.data.repository.reactive.ReactiveCrudRepository;
import reactor.core.publisher.Flux;
public interface ProductCategoryRepository extends ReactiveCrudRepository<ProductCategory, Long> {
Flux<ProductCategory> findByUserId(Long userId);
Flux<ProductCategory> findByUserIdAndCommodityCode(Long userId, String commodityCode);
}

View File

@@ -0,0 +1,9 @@
package com.kifi.api.repository.inventory;
import com.kifi.api.entity.inventory.ProductImage;
import org.springframework.data.repository.reactive.ReactiveCrudRepository;
import reactor.core.publisher.Flux;
public interface ProductImageRepository extends ReactiveCrudRepository<ProductImage, Long> {
Flux<ProductImage> findByProductId(Long productId);
}

View File

@@ -0,0 +1,15 @@
package com.kifi.api.repository.inventory;
import com.kifi.api.entity.inventory.Product;
import org.springframework.data.domain.Pageable;
import org.springframework.data.repository.reactive.ReactiveCrudRepository;
import reactor.core.publisher.Flux;
public interface ProductRepository extends ReactiveCrudRepository<Product, Long> {
Flux<Product> findByUserId(Long userId, Pageable pageable);
@org.springframework.data.r2dbc.repository.Query("SELECT * FROM products WHERE user_id = :userId AND (:keyword IS NULL OR :keyword = '' OR LOWER(name) LIKE LOWER(CONCAT('%', :keyword, '%')) OR LOWER(sku) LIKE LOWER(CONCAT('%', :keyword, '%'))) OFFSET :offset LIMIT :limit")
Flux<Product> searchProducts(Long userId, String keyword, long offset, int limit);
Flux<Product> findByCategoryId(Long categoryId);
}

View File

@@ -0,0 +1,9 @@
package com.kifi.api.repository.inventory;
import com.kifi.api.entity.inventory.UnitOfMeasure;
import org.springframework.data.repository.reactive.ReactiveCrudRepository;
import reactor.core.publisher.Flux;
public interface UnitOfMeasureRepository extends ReactiveCrudRepository<UnitOfMeasure, Long> {
Flux<UnitOfMeasure> findByUserId(Long userId);
}

View File

@@ -0,0 +1,11 @@
package com.kifi.api.repository.invoice;
import com.kifi.api.entity.invoice.InvoiceItem;
import org.springframework.data.repository.reactive.ReactiveCrudRepository;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
public interface InvoiceItemRepository extends ReactiveCrudRepository<InvoiceItem, Long> {
Flux<InvoiceItem> findByInvoiceId(Long invoiceId);
Mono<Void> deleteByInvoiceId(Long invoiceId);
}

View File

@@ -0,0 +1,9 @@
package com.kifi.api.repository.invoice;
import com.kifi.api.entity.invoice.InvoicePayment;
import org.springframework.data.repository.reactive.ReactiveCrudRepository;
import reactor.core.publisher.Flux;
public interface InvoicePaymentRepository extends ReactiveCrudRepository<InvoicePayment, Long> {
Flux<InvoicePayment> findByInvoiceId(Long invoiceId);
}

View File

@@ -0,0 +1,12 @@
package com.kifi.api.repository.invoice;
import com.kifi.api.entity.invoice.Invoice;
import org.springframework.data.repository.reactive.ReactiveCrudRepository;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
public interface InvoiceRepository extends ReactiveCrudRepository<Invoice, Long> {
Flux<Invoice> findByUserId(Long userId);
Flux<Invoice> findByUserIdAndCustomerId(Long userId, Long customerId);
Mono<Invoice> findByUserIdAndInvoiceNumber(Long userId, String invoiceNumber);
}

View File

@@ -0,0 +1,11 @@
package com.kifi.api.repository.vendor;
import com.kifi.api.entity.vendor.PurchaseOrderItem;
import org.springframework.data.repository.reactive.ReactiveCrudRepository;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
public interface PurchaseOrderItemRepository extends ReactiveCrudRepository<PurchaseOrderItem, Long> {
Flux<PurchaseOrderItem> findByPoId(Long poId);
Mono<Void> deleteByPoId(Long poId);
}

View File

@@ -0,0 +1,11 @@
package com.kifi.api.repository.vendor;
import com.kifi.api.entity.vendor.PurchaseOrder;
import org.springframework.data.repository.reactive.ReactiveCrudRepository;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
public interface PurchaseOrderRepository extends ReactiveCrudRepository<PurchaseOrder, Long> {
Flux<PurchaseOrder> findByUserId(Long userId);
Mono<PurchaseOrder> findByUserIdAndId(Long userId, Long id);
}

View File

@@ -0,0 +1,9 @@
package com.kifi.api.repository.vendor;
import com.kifi.api.entity.vendor.PurchasePayment;
import org.springframework.data.repository.reactive.ReactiveCrudRepository;
import reactor.core.publisher.Flux;
public interface PurchasePaymentRepository extends ReactiveCrudRepository<PurchasePayment, Long> {
Flux<PurchasePayment> findByPoId(Long poId);
}

View File

@@ -0,0 +1,9 @@
package com.kifi.api.repository.vendor;
import com.kifi.api.entity.vendor.Vendor;
import org.springframework.data.repository.reactive.ReactiveCrudRepository;
import reactor.core.publisher.Flux;
public interface VendorRepository extends ReactiveCrudRepository<Vendor, Long> {
Flux<Vendor> findByUserId(Long userId);
}

Some files were not shown because too many files have changed in this diff Show More