feat: Implement invoice editing, add company registration number to model and PDF, and refine PDF filename generation.
This commit is contained in:
parent
6643aa4157
commit
b11ae890ce
10 changed files with 364 additions and 96 deletions
|
|
@ -1,62 +1,83 @@
|
||||||
|
Resolving dependencies...
|
||||||
|
Downloading packages...
|
||||||
|
geolocator 13.0.4 (14.0.2 available)
|
||||||
|
geolocator_android 4.6.2 (5.0.2 available)
|
||||||
|
image 4.5.4 (4.7.2 available)
|
||||||
|
meta 1.17.0 (1.18.1 available)
|
||||||
|
petitparser 7.0.1 (7.0.2 available)
|
||||||
|
Got dependencies!
|
||||||
|
5 packages have newer versions incompatible with dependency constraints.
|
||||||
|
Try `flutter pub outdated` for more information.
|
||||||
Analyzing gemi_invoice_backup2...
|
Analyzing gemi_invoice_backup2...
|
||||||
|
|
||||||
warning • The value of the field '_lastGeneratedInvoice' isn't used • lib/main.dart:43:12 • unused_field
|
info • Parameter 'key' could be a super parameter • lib/screens/activity_log_screen.dart:7:9 • use_super_parameters
|
||||||
error • The body might complete normally, causing 'null' to be returned, but the return type, 'Widget', is a potentially non-nullable type • lib/main.dart:61:10 • body_might_complete_normally
|
info • 'withOpacity' is deprecated and shouldn't be used. Use .withValues() to avoid precision loss • lib/screens/activity_log_screen.dart:94:34 • deprecated_member_use
|
||||||
warning • The label 'appBar' isn't used • lib/main.dart:62:7 • unused_label
|
info • Parameter 'key' could be a super parameter • lib/screens/barcode_scanner_screen.dart:5:9 • use_super_parameters
|
||||||
error • Expected to find ';' • lib/main.dart:65:7 • expected_token
|
info • Parameter 'key' could be a super parameter • lib/screens/company_info_screen.dart:8:9 • use_super_parameters
|
||||||
error • Expected an identifier • lib/main.dart:65:8 • missing_identifier
|
info • Don't use 'BuildContext's across async gaps • lib/screens/company_info_screen.dart:63:26 • use_build_context_synchronously
|
||||||
error • Unexpected text ';' • lib/main.dart:65:8 • unexpected_token
|
info • Don't use 'BuildContext's across async gaps • lib/screens/company_info_screen.dart:64:19 • use_build_context_synchronously
|
||||||
warning • The label 'drawer' isn't used • lib/main.dart:66:7 • unused_label
|
info • Parameter 'key' could be a super parameter • lib/screens/customer_master_screen.dart:7:9 • use_super_parameters
|
||||||
error • Expected to find ';' • lib/main.dart:92:7 • expected_token
|
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 • lib/screens/customer_master_screen.dart:60:19 • deprecated_member_use
|
||||||
error • Expected an identifier • lib/main.dart:92:8 • missing_identifier
|
info • The 'child' argument should be last in widget constructor invocations • lib/screens/customer_master_screen.dart:164:9 • sort_child_properties_last
|
||||||
error • Unexpected text ';' • lib/main.dart:92:8 • unexpected_token
|
info • Parameter 'key' could be a super parameter • lib/screens/customer_picker_modal.dart:11:9 • use_super_parameters
|
||||||
warning • The label 'body' isn't used • lib/main.dart:94:7 • unused_label
|
info • The private field _searchQuery could be 'final' • lib/screens/customer_picker_modal.dart:22:10 • prefer_final_fields
|
||||||
error • Expected to find ';' • lib/main.dart:106:7 • expected_token
|
warning • The value of the field '_searchQuery' isn't used • lib/screens/customer_picker_modal.dart:22:10 • unused_field
|
||||||
error • Expected an identifier • lib/main.dart:106:8 • missing_identifier
|
info • The private field _allCustomers could be 'final' • lib/screens/customer_picker_modal.dart:23:18 • prefer_final_fields
|
||||||
error • Expected to find ';' • lib/main.dart:106:8 • expected_token
|
warning • The value of the field '_allCustomers' isn't used • lib/screens/customer_picker_modal.dart:23:18 • unused_field
|
||||||
error • Unexpected text ';' • lib/main.dart:106:8 • unexpected_token
|
info • Don't use 'BuildContext's across async gaps • lib/screens/customer_picker_modal.dart:67:28 • use_build_context_synchronously
|
||||||
error • Expected an identifier • lib/main.dart:107:5 • missing_identifier
|
info • Don't use 'BuildContext's across async gaps • lib/screens/customer_picker_modal.dart:140:29 • use_build_context_synchronously
|
||||||
error • Unexpected text ';' • lib/main.dart:107:5 • unexpected_token
|
info • Don't use 'BuildContext's across async gaps • lib/screens/customer_picker_modal.dart:165:29 • use_build_context_synchronously
|
||||||
info • Unnecessary empty statement • lib/main.dart:107:6 • empty_statements
|
info • Parameter 'key' could be a super parameter • lib/screens/gps_history_screen.dart:6:9 • use_super_parameters
|
||||||
info • The imported package 'uuid' isn't a dependency of the importing package • lib/models/customer_model.dart:1:8 • depend_on_referenced_packages
|
info • Parameter 'key' could be a super parameter • lib/screens/invoice_detail_page.dart:19:9 • use_super_parameters
|
||||||
warning • Unused import: 'package:uuid/uuid.dart' • lib/models/customer_model.dart:1:8 • unused_import
|
info • Don't use 'BuildContext's across async gaps • lib/screens/invoice_detail_page.dart:136:28 • use_build_context_synchronously
|
||||||
error • The named parameter 'unitPrice' is required, but there's no corresponding argument • lib/models/invoice_models.dart:30:12 • missing_required_argument
|
info • 'Share' is deprecated and shouldn't be used. Use SharePlus instead • lib/screens/invoice_detail_page.dart:144:5 • deprecated_member_use
|
||||||
error • The named parameter 'unit_price' isn't defined • lib/models/invoice_models.dart:34:7 • undefined_named_parameter
|
info • 'share' is deprecated and shouldn't be used. Use SharePlus.instance.share() instead • lib/screens/invoice_detail_page.dart:144:11 • deprecated_member_use
|
||||||
warning • The value of the local variable 'amountFormatter' isn't used • lib/models/invoice_models.dart:88:11 • unused_local_variable
|
info • Don't use 'BuildContext's across async gaps • lib/screens/invoice_detail_page.dart:160:9 • use_build_context_synchronously
|
||||||
info • The imported package 'uuid' isn't a dependency of the importing package • lib/screens/customer_picker_modal.dart:3:8 • depend_on_referenced_packages
|
warning • Dead code • lib/screens/invoice_detail_page.dart:170:47 • dead_code
|
||||||
error • Undefined class 'Customer' • lib/screens/customer_picker_modal.dart:8:18 • undefined_class
|
warning • The left operand can't be null, so the right operand is never executed • lib/screens/invoice_detail_page.dart:170:50 • dead_null_aware_expression
|
||||||
info • Parameter 'key' could be a super parameter • lib/screens/customer_picker_modal.dart:10:9 • use_super_parameters
|
warning • The left operand can't be null, so the right operand is never executed • lib/screens/invoice_detail_page.dart:171:58 • dead_null_aware_expression
|
||||||
error • The name 'Customer' isn't a type, so it can't be used as a type argument • lib/screens/customer_picker_modal.dart:22:8 • non_type_as_type_argument
|
warning • The '!' will have no effect because the receiver can't be null • lib/screens/invoice_detail_page.dart:180:65 • unnecessary_non_null_assertion
|
||||||
error • The name 'Customer' isn't a type, so it can't be used as a type argument • lib/screens/customer_picker_modal.dart:23:8 • non_type_as_type_argument
|
error • The method 'InvoiceInputForm' isn't defined for the type '_InvoiceDetailPageState' • lib/screens/invoice_detail_page.dart:230:45 • undefined_method
|
||||||
error • The property 'formalName' can't be unconditionally accessed because the receiver can be 'null' • lib/screens/customer_picker_modal.dart:47:25 • unchecked_use_of_nullable_value
|
error • 1 positional argument expected by 'getAllInvoices', but 0 found • lib/screens/invoice_detail_page.dart:240:62 • not_enough_positional_arguments
|
||||||
error • The property 'displayName' can't be unconditionally accessed because the receiver can be 'null' • lib/screens/customer_picker_modal.dart:48:22 • unchecked_use_of_nullable_value
|
warning • The value of the local variable 'dateFormatter' isn't used • lib/screens/invoice_detail_page.dart:307:11 • unused_local_variable
|
||||||
info • Don't use 'BuildContext's across async gaps • lib/screens/customer_picker_modal.dart:77:28 • use_build_context_synchronously
|
info • 'withOpacity' is deprecated and shouldn't be used. Use .withValues() to avoid precision loss • lib/screens/invoice_detail_page.dart:346:114 • deprecated_member_use
|
||||||
error • Undefined class 'Customer' • lib/screens/customer_picker_modal.dart:87:5 • undefined_class
|
info • 'withOpacity' is deprecated and shouldn't be used. Use .withValues() to avoid precision loss • lib/screens/invoice_detail_page.dart:376:84 • deprecated_member_use
|
||||||
error • The method 'Customer' isn't defined for the type '_CustomerPickerModalState' • lib/screens/customer_picker_modal.dart:141:19 • undefined_method
|
info • 'Share' is deprecated and shouldn't be used. Use SharePlus instead • lib/screens/invoice_detail_page.dart:614:13 • deprecated_member_use
|
||||||
info • Don't use 'BuildContext's across async gaps • lib/screens/customer_picker_modal.dart:150:29 • use_build_context_synchronously
|
info • 'shareXFiles' is deprecated and shouldn't be used. Use SharePlus.instance.share() instead • lib/screens/invoice_detail_page.dart:614:19 • deprecated_member_use
|
||||||
error • Undefined class 'Customer' • lib/screens/customer_picker_modal.dart:164:23 • undefined_class
|
warning • The declaration '_SummaryRow' isn't referenced • lib/screens/invoice_detail_page.dart:661:7 • unused_element
|
||||||
info • Don't use 'BuildContext's across async gaps • lib/screens/customer_picker_modal.dart:175:29 • use_build_context_synchronously
|
warning • A value for optional parameter 'isBold' isn't ever given • lib/screens/invoice_detail_page.dart:664:51 • unused_element_parameter
|
||||||
warning • Unused import: 'dart:io' • lib/screens/invoice_detail_page.dart:1:8 • unused_import
|
info • Parameter 'key' could be a super parameter • lib/screens/invoice_history_screen.dart:15:9 • use_super_parameters
|
||||||
warning • Unused import: '../models/customer_model.dart' • lib/screens/invoice_detail_page.dart:7:8 • unused_import
|
warning • The value of the field '_isLoading' isn't used • lib/screens/invoice_history_screen.dart:26:8 • unused_field
|
||||||
info • Parameter 'key' could be a super parameter • lib/screens/invoice_detail_page.dart:16:9 • use_super_parameters
|
warning • The value of the local variable 'amountFormatter' isn't used • lib/screens/invoice_history_screen.dart:97:11 • unused_local_variable
|
||||||
info • Don't use 'BuildContext's across async gaps • lib/screens/invoice_detail_page.dart:120:28 • use_build_context_synchronously
|
warning • The value of the local variable 'dateFormatter' isn't used • lib/screens/invoice_history_screen.dart:98:11 • unused_local_variable
|
||||||
info • 'Share' is deprecated and shouldn't be used. Use SharePlus instead • lib/screens/invoice_detail_page.dart:128:5 • deprecated_member_use
|
error • Undefined name 'children' • lib/screens/invoice_history_screen.dart:235:9 • undefined_identifier
|
||||||
info • 'share' is deprecated and shouldn't be used. Use SharePlus.instance.share() instead • lib/screens/invoice_detail_page.dart:128:11 • deprecated_member_use
|
error • Expected to find ')' • lib/screens/invoice_history_screen.dart:235:17 • expected_token
|
||||||
info • Use a 'SizedBox' to add whitespace to a layout • lib/screens/invoice_detail_page.dart:283:14 • sized_box_for_whitespace
|
error • Expected to find ']' • lib/screens/invoice_history_screen.dart:235:17 • expected_token
|
||||||
info • 'Share' is deprecated and shouldn't be used. Use SharePlus instead • lib/screens/invoice_detail_page.dart:327:43 • deprecated_member_use
|
warning • Unused import: 'package:uuid/uuid.dart' • lib/screens/invoice_input_screen.dart:2:8 • unused_import
|
||||||
info • 'shareXFiles' is deprecated and shouldn't be used. Use SharePlus.instance.share() instead • lib/screens/invoice_detail_page.dart:327:49 • deprecated_member_use
|
info • Parameter 'key' could be a super parameter • lib/screens/invoice_input_screen.dart:20:9 • use_super_parameters
|
||||||
warning • Unused import: '../models/customer_model.dart' • lib/screens/invoice_history_screen.dart:4:8 • unused_import
|
warning • The value of the field '_status' isn't used • lib/screens/invoice_input_screen.dart:41:10 • unused_field
|
||||||
info • Parameter 'key' could be a super parameter • lib/screens/invoice_history_screen.dart:10:9 • use_super_parameters
|
info • The private field _signaturePath could be 'final' • lib/screens/invoice_input_screen.dart:44:17 • prefer_final_fields
|
||||||
info • The imported package 'uuid' isn't a dependency of the importing package • lib/screens/invoice_input_screen.dart:2:8 • depend_on_referenced_packages
|
info • Don't use 'BuildContext's across async gaps • lib/screens/invoice_input_screen.dart:137:30 • use_build_context_synchronously
|
||||||
info • Parameter 'key' could be a super parameter • lib/screens/invoice_input_screen.dart:14:9 • use_super_parameters
|
info • Don't use 'BuildContext's across async gaps • lib/screens/invoice_input_screen.dart:141:28 • use_build_context_synchronously
|
||||||
info • The private field _customerBuffer could be 'final' • lib/screens/invoice_input_screen.dart:29:18 • prefer_final_fields
|
info • Don't use 'BuildContext's across async gaps • lib/screens/invoice_input_screen.dart:142:21 • use_build_context_synchronously
|
||||||
warning • The value of the field '_customerBuffer' isn't used • lib/screens/invoice_input_screen.dart:29:18 • unused_field
|
error • The method 'copyWith' isn't defined for the type 'InvoiceItem' • lib/screens/invoice_input_screen.dart:393:50 • undefined_method
|
||||||
error • A value of type 'Object?' can't be assigned to a variable of type 'Customer?' • lib/screens/invoice_input_screen.dart:87:35 • invalid_assignment
|
info • 'activeColor' is deprecated and shouldn't be used. Use activeThumbColor instead. This feature was deprecated after v3.31.0-2.0.pre • lib/screens/invoice_input_screen.dart:600:13 • deprecated_member_use
|
||||||
error • The property 'formalName' can't be unconditionally accessed because the receiver can be 'null' • lib/screens/invoice_input_screen.dart:88:49 • unchecked_use_of_nullable_value
|
info • 'withOpacity' is deprecated and shouldn't be used. Use .withValues() to avoid precision loss • lib/screens/invoice_input_screen.dart:619:51 • deprecated_member_use
|
||||||
error • The property 'formalName' can't be unconditionally accessed because the receiver can be 'null' • lib/screens/invoice_input_screen.dart:89:38 • unchecked_use_of_nullable_value
|
warning • Unused import: 'package:path_provider/path_provider.dart' • lib/screens/management_screen.dart:6:8 • unused_import
|
||||||
info • Parameter 'key' could be a super parameter • lib/screens/product_picker_modal.dart:8:9 • use_super_parameters
|
info • Parameter 'key' could be a super parameter • lib/screens/management_screen.dart:16:9 • use_super_parameters
|
||||||
info • 'desiredAccuracy' is deprecated and shouldn't be used. use settings parameter with AndroidSettings, AppleSettings, WebSettings, or LocationSettings • lib/services/location_service.dart:28:9 • deprecated_member_use
|
info • 'Share' is deprecated and shouldn't be used. Use SharePlus instead • lib/screens/management_screen.dart:147:11 • deprecated_member_use
|
||||||
info • 'timeLimit' is deprecated and shouldn't be used. use settings parameter with AndroidSettings, AppleSettings, WebSettings, or LocationSettings • lib/services/location_service.dart:29:9 • deprecated_member_use
|
info • 'share' is deprecated and shouldn't be used. Use SharePlus.instance.share() instead • lib/screens/management_screen.dart:147:17 • deprecated_member_use
|
||||||
info • The import of 'dart:typed_data' is unnecessary because all of the used elements are also provided by the import of 'package:flutter/services.dart' • lib/services/pdf_generator.dart:2:8 • unnecessary_import
|
info • 'Share' is deprecated and shouldn't be used. Use SharePlus instead • lib/screens/management_screen.dart:154:13 • deprecated_member_use
|
||||||
|
info • 'shareXFiles' is deprecated and shouldn't be used. Use SharePlus.instance.share() instead • lib/screens/management_screen.dart:154:19 • deprecated_member_use
|
||||||
|
info • Parameter 'key' could be a super parameter • lib/screens/product_master_screen.dart:8:9 • use_super_parameters
|
||||||
|
info • Don't use 'BuildContext's across async gaps • lib/screens/product_master_screen.dart:182:55 • use_build_context_synchronously
|
||||||
|
info • The 'child' argument should be last in widget constructor invocations • lib/screens/product_master_screen.dart:199:9 • sort_child_properties_last
|
||||||
|
info • Parameter 'key' could be a super parameter • lib/screens/product_picker_modal.dart:11:9 • use_super_parameters
|
||||||
|
info • Parameter 'key' could be a super parameter • lib/screens/sales_report_screen.dart:6:9 • use_super_parameters
|
||||||
|
warning • Unused import: 'package:crypto/crypto.dart' • lib/services/pdf_generator.dart:7:8 • unused_import
|
||||||
|
info • Unnecessary braces in a string interpolation • lib/services/pdf_generator.dart:274:24 • unnecessary_brace_in_string_interps
|
||||||
|
info • Unnecessary braces in a string interpolation • lib/services/pdf_generator.dart:274:63 • unnecessary_brace_in_string_interps
|
||||||
|
info • Unnecessary braces in a string interpolation • lib/services/pdf_generator.dart:274:96 • unnecessary_brace_in_string_interps
|
||||||
|
info • Use the null-aware marker '?' rather than a null check via an 'if' • lib/services/pdf_generator.dart:346:13 • use_null_aware_elements
|
||||||
|
info • Parameter 'key' could be a super parameter • lib/widgets/slide_to_unlock.dart:8:9 • use_super_parameters
|
||||||
|
|
||||||
58 issues found. (ran in 23.0s)
|
|
||||||
|
|
|
||||||
76
analyze_output_v2.txt
Normal file
76
analyze_output_v2.txt
Normal file
|
|
@ -0,0 +1,76 @@
|
||||||
|
Resolving dependencies...
|
||||||
|
Downloading packages...
|
||||||
|
geolocator 13.0.4 (14.0.2 available)
|
||||||
|
geolocator_android 4.6.2 (5.0.2 available)
|
||||||
|
image 4.5.4 (4.7.2 available)
|
||||||
|
meta 1.17.0 (1.18.1 available)
|
||||||
|
petitparser 7.0.1 (7.0.2 available)
|
||||||
|
Got dependencies!
|
||||||
|
5 packages have newer versions incompatible with dependency constraints.
|
||||||
|
Try `flutter pub outdated` for more information.
|
||||||
|
Analyzing gemi_invoice_backup2...
|
||||||
|
|
||||||
|
info • Parameter 'key' could be a super parameter • lib/screens/activity_log_screen.dart:7:9 • use_super_parameters
|
||||||
|
info • 'withOpacity' is deprecated and shouldn't be used. Use .withValues() to avoid precision loss • lib/screens/activity_log_screen.dart:94:34 • deprecated_member_use
|
||||||
|
info • Parameter 'key' could be a super parameter • lib/screens/barcode_scanner_screen.dart:5:9 • use_super_parameters
|
||||||
|
info • Parameter 'key' could be a super parameter • lib/screens/company_info_screen.dart:8:9 • use_super_parameters
|
||||||
|
info • Don't use 'BuildContext's across async gaps • lib/screens/company_info_screen.dart:63:26 • use_build_context_synchronously
|
||||||
|
info • Don't use 'BuildContext's across async gaps • lib/screens/company_info_screen.dart:64:19 • use_build_context_synchronously
|
||||||
|
info • Parameter 'key' could be a super parameter • lib/screens/customer_master_screen.dart:7:9 • use_super_parameters
|
||||||
|
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 • lib/screens/customer_master_screen.dart:60:19 • deprecated_member_use
|
||||||
|
info • The 'child' argument should be last in widget constructor invocations • lib/screens/customer_master_screen.dart:164:9 • sort_child_properties_last
|
||||||
|
info • Parameter 'key' could be a super parameter • lib/screens/customer_picker_modal.dart:11:9 • use_super_parameters
|
||||||
|
info • The private field _searchQuery could be 'final' • lib/screens/customer_picker_modal.dart:22:10 • prefer_final_fields
|
||||||
|
warning • The value of the field '_searchQuery' isn't used • lib/screens/customer_picker_modal.dart:22:10 • unused_field
|
||||||
|
info • The private field _allCustomers could be 'final' • lib/screens/customer_picker_modal.dart:23:18 • prefer_final_fields
|
||||||
|
warning • The value of the field '_allCustomers' isn't used • lib/screens/customer_picker_modal.dart:23:18 • unused_field
|
||||||
|
info • Don't use 'BuildContext's across async gaps • lib/screens/customer_picker_modal.dart:67:28 • use_build_context_synchronously
|
||||||
|
info • Don't use 'BuildContext's across async gaps • lib/screens/customer_picker_modal.dart:140:29 • use_build_context_synchronously
|
||||||
|
info • Don't use 'BuildContext's across async gaps • lib/screens/customer_picker_modal.dart:165:29 • use_build_context_synchronously
|
||||||
|
info • Parameter 'key' could be a super parameter • lib/screens/gps_history_screen.dart:6:9 • use_super_parameters
|
||||||
|
info • Parameter 'key' could be a super parameter • lib/screens/invoice_detail_page.dart:20:9 • use_super_parameters
|
||||||
|
info • Don't use 'BuildContext's across async gaps • lib/screens/invoice_detail_page.dart:137:28 • use_build_context_synchronously
|
||||||
|
info • 'Share' is deprecated and shouldn't be used. Use SharePlus instead • lib/screens/invoice_detail_page.dart:145:5 • deprecated_member_use
|
||||||
|
info • 'share' is deprecated and shouldn't be used. Use SharePlus.instance.share() instead • lib/screens/invoice_detail_page.dart:145:11 • deprecated_member_use
|
||||||
|
info • Don't use 'BuildContext's across async gaps • lib/screens/invoice_detail_page.dart:161:9 • use_build_context_synchronously
|
||||||
|
warning • Dead code • lib/screens/invoice_detail_page.dart:171:47 • dead_code
|
||||||
|
warning • The left operand can't be null, so the right operand is never executed • lib/screens/invoice_detail_page.dart:171:50 • dead_null_aware_expression
|
||||||
|
warning • The left operand can't be null, so the right operand is never executed • lib/screens/invoice_detail_page.dart:172:58 • dead_null_aware_expression
|
||||||
|
warning • The '!' will have no effect because the receiver can't be null • lib/screens/invoice_detail_page.dart:181:65 • unnecessary_non_null_assertion
|
||||||
|
warning • The value of the local variable 'dateFormatter' isn't used • lib/screens/invoice_detail_page.dart:310:11 • unused_local_variable
|
||||||
|
info • 'withOpacity' is deprecated and shouldn't be used. Use .withValues() to avoid precision loss • lib/screens/invoice_detail_page.dart:349:114 • deprecated_member_use
|
||||||
|
info • 'withOpacity' is deprecated and shouldn't be used. Use .withValues() to avoid precision loss • lib/screens/invoice_detail_page.dart:379:84 • deprecated_member_use
|
||||||
|
info • 'Share' is deprecated and shouldn't be used. Use SharePlus instead • lib/screens/invoice_detail_page.dart:617:13 • deprecated_member_use
|
||||||
|
info • 'shareXFiles' is deprecated and shouldn't be used. Use SharePlus.instance.share() instead • lib/screens/invoice_detail_page.dart:617:19 • deprecated_member_use
|
||||||
|
warning • The declaration '_SummaryRow' isn't referenced • lib/screens/invoice_detail_page.dart:664:7 • unused_element
|
||||||
|
warning • A value for optional parameter 'isBold' isn't ever given • lib/screens/invoice_detail_page.dart:667:51 • unused_element_parameter
|
||||||
|
warning • Unused import: '../models/customer_model.dart' • lib/screens/invoice_history_screen.dart:4:8 • unused_import
|
||||||
|
info • Parameter 'key' could be a super parameter • lib/screens/invoice_history_screen.dart:15:9 • use_super_parameters
|
||||||
|
warning • Unused import: 'package:uuid/uuid.dart' • lib/screens/invoice_input_screen.dart:2:8 • unused_import
|
||||||
|
info • Parameter 'key' could be a super parameter • lib/screens/invoice_input_screen.dart:20:9 • use_super_parameters
|
||||||
|
warning • The value of the field '_status' isn't used • lib/screens/invoice_input_screen.dart:41:10 • unused_field
|
||||||
|
info • The private field _signaturePath could be 'final' • lib/screens/invoice_input_screen.dart:44:17 • prefer_final_fields
|
||||||
|
info • Don't use 'BuildContext's across async gaps • lib/screens/invoice_input_screen.dart:137:30 • use_build_context_synchronously
|
||||||
|
info • Don't use 'BuildContext's across async gaps • lib/screens/invoice_input_screen.dart:141:28 • use_build_context_synchronously
|
||||||
|
info • Don't use 'BuildContext's across async gaps • lib/screens/invoice_input_screen.dart:142:21 • use_build_context_synchronously
|
||||||
|
error • The method 'copyWith' isn't defined for the type 'InvoiceItem' • lib/screens/invoice_input_screen.dart:393:50 • undefined_method
|
||||||
|
info • 'activeColor' is deprecated and shouldn't be used. Use activeThumbColor instead. This feature was deprecated after v3.31.0-2.0.pre • lib/screens/invoice_input_screen.dart:600:13 • deprecated_member_use
|
||||||
|
info • 'withOpacity' is deprecated and shouldn't be used. Use .withValues() to avoid precision loss • lib/screens/invoice_input_screen.dart:619:51 • deprecated_member_use
|
||||||
|
warning • Unused import: 'package:path_provider/path_provider.dart' • lib/screens/management_screen.dart:6:8 • unused_import
|
||||||
|
info • Parameter 'key' could be a super parameter • lib/screens/management_screen.dart:16:9 • use_super_parameters
|
||||||
|
info • 'Share' is deprecated and shouldn't be used. Use SharePlus instead • lib/screens/management_screen.dart:147:11 • deprecated_member_use
|
||||||
|
info • 'share' is deprecated and shouldn't be used. Use SharePlus.instance.share() instead • lib/screens/management_screen.dart:147:17 • deprecated_member_use
|
||||||
|
info • 'Share' is deprecated and shouldn't be used. Use SharePlus instead • lib/screens/management_screen.dart:154:13 • deprecated_member_use
|
||||||
|
info • 'shareXFiles' is deprecated and shouldn't be used. Use SharePlus.instance.share() instead • lib/screens/management_screen.dart:154:19 • deprecated_member_use
|
||||||
|
info • Parameter 'key' could be a super parameter • lib/screens/product_master_screen.dart:8:9 • use_super_parameters
|
||||||
|
info • Don't use 'BuildContext's across async gaps • lib/screens/product_master_screen.dart:182:55 • use_build_context_synchronously
|
||||||
|
info • The 'child' argument should be last in widget constructor invocations • lib/screens/product_master_screen.dart:199:9 • sort_child_properties_last
|
||||||
|
info • Parameter 'key' could be a super parameter • lib/screens/product_picker_modal.dart:11:9 • use_super_parameters
|
||||||
|
info • Parameter 'key' could be a super parameter • lib/screens/sales_report_screen.dart:6:9 • use_super_parameters
|
||||||
|
warning • Unused import: 'package:crypto/crypto.dart' • lib/services/pdf_generator.dart:7:8 • unused_import
|
||||||
|
info • Unnecessary braces in a string interpolation • lib/services/pdf_generator.dart:274:24 • unnecessary_brace_in_string_interps
|
||||||
|
info • Unnecessary braces in a string interpolation • lib/services/pdf_generator.dart:274:63 • unnecessary_brace_in_string_interps
|
||||||
|
info • Unnecessary braces in a string interpolation • lib/services/pdf_generator.dart:274:96 • unnecessary_brace_in_string_interps
|
||||||
|
info • Use the null-aware marker '?' rather than a null check via an 'if' • lib/services/pdf_generator.dart:346:13 • use_null_aware_elements
|
||||||
|
info • Parameter 'key' could be a super parameter • lib/widgets/slide_to_unlock.dart:8:9 • use_super_parameters
|
||||||
|
|
||||||
|
|
@ -6,6 +6,7 @@ class CompanyInfo {
|
||||||
final double defaultTaxRate;
|
final double defaultTaxRate;
|
||||||
final String? sealPath; // 角印(印鑑)の画像パス
|
final String? sealPath; // 角印(印鑑)の画像パス
|
||||||
final String taxDisplayMode; // 'normal', 'hidden', 'text_only'
|
final String taxDisplayMode; // 'normal', 'hidden', 'text_only'
|
||||||
|
final String? registrationNumber; // 追加: インボイス登録番号 (T番号)
|
||||||
|
|
||||||
CompanyInfo({
|
CompanyInfo({
|
||||||
required this.name,
|
required this.name,
|
||||||
|
|
@ -15,6 +16,7 @@ class CompanyInfo {
|
||||||
this.defaultTaxRate = 0.10,
|
this.defaultTaxRate = 0.10,
|
||||||
this.sealPath,
|
this.sealPath,
|
||||||
this.taxDisplayMode = 'normal',
|
this.taxDisplayMode = 'normal',
|
||||||
|
this.registrationNumber, // 追加
|
||||||
});
|
});
|
||||||
|
|
||||||
Map<String, dynamic> toMap() {
|
Map<String, dynamic> toMap() {
|
||||||
|
|
@ -27,6 +29,7 @@ class CompanyInfo {
|
||||||
'default_tax_rate': defaultTaxRate,
|
'default_tax_rate': defaultTaxRate,
|
||||||
'seal_path': sealPath,
|
'seal_path': sealPath,
|
||||||
'tax_display_mode': taxDisplayMode,
|
'tax_display_mode': taxDisplayMode,
|
||||||
|
'registration_number': registrationNumber, // 追加
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -39,6 +42,7 @@ class CompanyInfo {
|
||||||
defaultTaxRate: map['default_tax_rate'] ?? 0.10,
|
defaultTaxRate: map['default_tax_rate'] ?? 0.10,
|
||||||
sealPath: map['seal_path'],
|
sealPath: map['seal_path'],
|
||||||
taxDisplayMode: map['tax_display_mode'] ?? 'normal',
|
taxDisplayMode: map['tax_display_mode'] ?? 'normal',
|
||||||
|
registrationNumber: map['registration_number'], // 追加
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -50,6 +54,7 @@ class CompanyInfo {
|
||||||
double? defaultTaxRate,
|
double? defaultTaxRate,
|
||||||
String? sealPath,
|
String? sealPath,
|
||||||
String? taxDisplayMode,
|
String? taxDisplayMode,
|
||||||
|
String? registrationNumber, // 追加
|
||||||
}) {
|
}) {
|
||||||
return CompanyInfo(
|
return CompanyInfo(
|
||||||
name: name ?? this.name,
|
name: name ?? this.name,
|
||||||
|
|
@ -59,6 +64,7 @@ class CompanyInfo {
|
||||||
defaultTaxRate: defaultTaxRate ?? this.defaultTaxRate,
|
defaultTaxRate: defaultTaxRate ?? this.defaultTaxRate,
|
||||||
sealPath: sealPath ?? this.sealPath,
|
sealPath: sealPath ?? this.sealPath,
|
||||||
taxDisplayMode: taxDisplayMode ?? this.taxDisplayMode,
|
taxDisplayMode: taxDisplayMode ?? this.taxDisplayMode,
|
||||||
|
registrationNumber: registrationNumber ?? this.registrationNumber, // 追加
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,22 @@ class InvoiceItem {
|
||||||
unitPrice: map['unit_price'],
|
unitPrice: map['unit_price'],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
InvoiceItem copyWith({
|
||||||
|
String? id, // Added this to be complete
|
||||||
|
String? description,
|
||||||
|
int? quantity,
|
||||||
|
int? unitPrice,
|
||||||
|
String? productId,
|
||||||
|
}) {
|
||||||
|
return InvoiceItem(
|
||||||
|
id: id ?? this.id, // Added this to be complete
|
||||||
|
description: description ?? this.description,
|
||||||
|
quantity: quantity ?? this.quantity,
|
||||||
|
unitPrice: unitPrice ?? this.unitPrice,
|
||||||
|
productId: productId ?? this.productId,
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enum DocumentType {
|
enum DocumentType {
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'invoice_input_screen.dart'; // Add this line
|
||||||
import 'package:intl/intl.dart';
|
import 'package:intl/intl.dart';
|
||||||
import 'package:share_plus/share_plus.dart';
|
import 'package:share_plus/share_plus.dart';
|
||||||
import 'package:open_filex/open_filex.dart';
|
import 'package:open_filex/open_filex.dart';
|
||||||
|
|
@ -220,7 +221,29 @@ class _InvoiceDetailPageState extends State<InvoiceDetailPage> {
|
||||||
if (!_isEditing) ...[
|
if (!_isEditing) ...[
|
||||||
IconButton(icon: const Icon(Icons.grid_on), onPressed: _exportCsv, tooltip: "CSV出力"),
|
IconButton(icon: const Icon(Icons.grid_on), onPressed: _exportCsv, tooltip: "CSV出力"),
|
||||||
if (widget.isUnlocked)
|
if (widget.isUnlocked)
|
||||||
IconButton(icon: const Icon(Icons.edit), onPressed: () => setState(() => _isEditing = true)),
|
IconButton(
|
||||||
|
icon: const Icon(Icons.edit_note), // アイコン変更
|
||||||
|
tooltip: "詳細編集",
|
||||||
|
onPressed: () async {
|
||||||
|
await Navigator.push(
|
||||||
|
context,
|
||||||
|
MaterialPageRoute(
|
||||||
|
builder: (context) => InvoiceInputForm(
|
||||||
|
onInvoiceGenerated: (inv, path) {
|
||||||
|
// 保存完了時のコールバック(必要なら)
|
||||||
|
},
|
||||||
|
existingInvoice: _currentInvoice,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
// 戻ってきたらデータを再読み込み(リポジトリから取得)
|
||||||
|
final repo = InvoiceRepository();
|
||||||
|
final customerRepo = CustomerRepository();
|
||||||
|
final customers = await customerRepo.getAllCustomers();
|
||||||
|
final updated = (await repo.getAllInvoices(customers)).firstWhere((i) => i.id == _currentInvoice.id, orElse: () => _currentInvoice);
|
||||||
|
setState(() => _currentInvoice = updated);
|
||||||
|
},
|
||||||
|
),
|
||||||
] else ...[
|
] else ...[
|
||||||
if (isDraft)
|
if (isDraft)
|
||||||
TextButton.icon(
|
TextButton.icon(
|
||||||
|
|
@ -430,12 +453,14 @@ class _InvoiceDetailPageState extends State<InvoiceDetailPage> {
|
||||||
return Column(
|
return Column(
|
||||||
children: [
|
children: [
|
||||||
_buildSummaryRow("小計", formatter.format(subtotal), textColor),
|
_buildSummaryRow("小計", formatter.format(subtotal), textColor),
|
||||||
|
if (currentTaxRate > 0) ...[
|
||||||
if (_companyInfo?.taxDisplayMode == 'normal')
|
if (_companyInfo?.taxDisplayMode == 'normal')
|
||||||
_buildSummaryRow("消費税 (${(currentTaxRate * 100).toInt()}%)", formatter.format(tax), textColor),
|
_buildSummaryRow("消費税 (${(currentTaxRate * 100).toInt()}%)", formatter.format(tax), textColor),
|
||||||
if (_companyInfo?.taxDisplayMode == 'text_only')
|
if (_companyInfo?.taxDisplayMode == 'text_only')
|
||||||
_buildSummaryRow("消費税", "(税別)", textColor),
|
_buildSummaryRow("消費税", "(税別)", textColor),
|
||||||
|
],
|
||||||
const Divider(color: Colors.grey),
|
const Divider(color: Colors.grey),
|
||||||
_buildSummaryRow("合計金額", "¥${formatter.format(total)}", textColor, isTotal: true),
|
_buildSummaryRow(currentTaxRate > 0 ? "合計金額 (税込)" : "合計金額", "¥${formatter.format(total)}", textColor, isTotal: true),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -99,6 +99,7 @@ class _InvoiceHistoryScreenState extends State<InvoiceHistoryScreen> {
|
||||||
|
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
|
leading: const BackButton(), // 常に表示
|
||||||
title: GestureDetector(
|
title: GestureDetector(
|
||||||
onLongPress: () {
|
onLongPress: () {
|
||||||
Navigator.push(
|
Navigator.push(
|
||||||
|
|
@ -231,11 +232,14 @@ class _InvoiceHistoryScreenState extends State<InvoiceHistoryScreen> {
|
||||||
),
|
),
|
||||||
body: Column(
|
body: Column(
|
||||||
children: [
|
children: [
|
||||||
SlideToUnlock(
|
Padding(
|
||||||
|
padding: const EdgeInsets.all(16.0),
|
||||||
|
child: SlideToUnlock(
|
||||||
isLocked: !_isUnlocked,
|
isLocked: !_isUnlocked,
|
||||||
onUnlocked: _toggleUnlock,
|
onUnlocked: _toggleUnlock,
|
||||||
text: "スライドでロック解除",
|
text: "スライドでロック解除",
|
||||||
),
|
),
|
||||||
|
),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: _isLoading
|
child: _isLoading
|
||||||
? const Center(child: CircularProgressIndicator())
|
? const Center(child: CircularProgressIndicator())
|
||||||
|
|
@ -251,6 +255,7 @@ class _InvoiceHistoryScreenState extends State<InvoiceHistoryScreen> {
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
: ListView.builder(
|
: ListView.builder(
|
||||||
|
padding: const EdgeInsets.only(bottom: 100), // キーボードやFAB考慮
|
||||||
itemCount: _filteredInvoices.length,
|
itemCount: _filteredInvoices.length,
|
||||||
itemBuilder: (context, index) {
|
itemBuilder: (context, index) {
|
||||||
final invoice = _filteredInvoices[index];
|
final invoice = _filteredInvoices[index];
|
||||||
|
|
|
||||||
|
|
@ -15,10 +15,12 @@ import '../services/company_repository.dart';
|
||||||
|
|
||||||
class InvoiceInputForm extends StatefulWidget {
|
class InvoiceInputForm extends StatefulWidget {
|
||||||
final Function(Invoice invoice, String filePath) onInvoiceGenerated;
|
final Function(Invoice invoice, String filePath) onInvoiceGenerated;
|
||||||
|
final Invoice? existingInvoice; // 追加: 編集時の既存伝票
|
||||||
|
|
||||||
const InvoiceInputForm({
|
const InvoiceInputForm({
|
||||||
Key? key,
|
Key? key,
|
||||||
required this.onInvoiceGenerated,
|
required this.onInvoiceGenerated,
|
||||||
|
this.existingInvoice, // 追加
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|
@ -59,7 +61,20 @@ class _InvoiceInputFormState extends State<InvoiceInputForm> {
|
||||||
final companyInfo = await companyRepo.getCompanyInfo();
|
final companyInfo = await companyRepo.getCompanyInfo();
|
||||||
setState(() {
|
setState(() {
|
||||||
_companyInfo = companyInfo;
|
_companyInfo = companyInfo;
|
||||||
|
// 既存伝票がある場合は初期値を上書き
|
||||||
|
if (widget.existingInvoice != null) {
|
||||||
|
final inv = widget.existingInvoice!;
|
||||||
|
_selectedCustomer = inv.customer;
|
||||||
|
_items.addAll(inv.items);
|
||||||
|
_taxRate = inv.taxRate;
|
||||||
|
_includeTax = inv.taxRate > 0;
|
||||||
|
_documentType = inv.documentType;
|
||||||
|
_selectedDate = inv.date;
|
||||||
|
_isDraft = inv.isDraft;
|
||||||
|
if (inv.subject != null) _subjectController.text = inv.subject!;
|
||||||
|
} else {
|
||||||
_taxRate = companyInfo.defaultTaxRate;
|
_taxRate = companyInfo.defaultTaxRate;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -98,6 +113,7 @@ class _InvoiceInputFormState extends State<InvoiceInputForm> {
|
||||||
}
|
}
|
||||||
|
|
||||||
final invoice = Invoice(
|
final invoice = Invoice(
|
||||||
|
id: widget.existingInvoice?.id, // 既存IDがあれば引き継ぐ
|
||||||
customer: _selectedCustomer!,
|
customer: _selectedCustomer!,
|
||||||
date: _selectedDate,
|
date: _selectedDate,
|
||||||
items: _items,
|
items: _items,
|
||||||
|
|
@ -180,7 +196,7 @@ class _InvoiceInputFormState extends State<InvoiceInputForm> {
|
||||||
backgroundColor: themeColor,
|
backgroundColor: themeColor,
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
leading: const BackButton(),
|
leading: const BackButton(),
|
||||||
title: Text(_isDraft ? "伝票作成 (下書きモード)" : "販売アシスト1号 V1.5.03"),
|
title: Text(_isDraft ? "伝票作成 (下書き)" : "販売アシスト1号 V1.5.04"),
|
||||||
backgroundColor: _isDraft ? Colors.black87 : Colors.blueGrey,
|
backgroundColor: _isDraft ? Colors.black87 : Colors.blueGrey,
|
||||||
),
|
),
|
||||||
body: Column(
|
body: Column(
|
||||||
|
|
@ -298,7 +314,7 @@ class _InvoiceInputFormState extends State<InvoiceInputForm> {
|
||||||
leading: const Icon(Icons.business, color: Colors.blueGrey),
|
leading: const Icon(Icons.business, color: Colors.blueGrey),
|
||||||
title: Text(_selectedCustomer?.formalName ?? "取引先を選択してください",
|
title: Text(_selectedCustomer?.formalName ?? "取引先を選択してください",
|
||||||
style: TextStyle(color: _selectedCustomer == null ? Colors.grey : Colors.black87, fontWeight: FontWeight.bold)),
|
style: TextStyle(color: _selectedCustomer == null ? Colors.grey : Colors.black87, fontWeight: FontWeight.bold)),
|
||||||
subtitle: const Text("請求先マスターから選択"),
|
subtitle: const Text("顧客マスターから選択"), // 修正
|
||||||
trailing: const Icon(Icons.chevron_right),
|
trailing: const Icon(Icons.chevron_right),
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
await showModalBottomSheet(
|
await showModalBottomSheet(
|
||||||
|
|
@ -352,6 +368,42 @@ class _InvoiceInputFormState extends State<InvoiceInputForm> {
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
onTap: () {
|
||||||
|
// 簡易編集ダイアログ
|
||||||
|
final descCtrl = TextEditingController(text: item.description);
|
||||||
|
final qtyCtrl = TextEditingController(text: item.quantity.toString());
|
||||||
|
final priceCtrl = TextEditingController(text: item.unitPrice.toString());
|
||||||
|
showDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (context) => AlertDialog(
|
||||||
|
title: const Text("明細の編集"),
|
||||||
|
content: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
TextField(controller: descCtrl, decoration: const InputDecoration(labelText: "品名 / 項目")),
|
||||||
|
TextField(controller: qtyCtrl, decoration: const InputDecoration(labelText: "数量"), keyboardType: TextInputType.number),
|
||||||
|
TextField(controller: priceCtrl, decoration: const InputDecoration(labelText: "単価"), keyboardType: TextInputType.number),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
actions: [
|
||||||
|
TextButton(onPressed: () => Navigator.pop(context), child: const Text("キャンセル")),
|
||||||
|
ElevatedButton(
|
||||||
|
onPressed: () {
|
||||||
|
setState(() {
|
||||||
|
_items[idx] = item.copyWith(
|
||||||
|
description: descCtrl.text,
|
||||||
|
quantity: int.tryParse(qtyCtrl.text) ?? item.quantity,
|
||||||
|
unitPrice: int.tryParse(priceCtrl.text) ?? item.unitPrice,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
Navigator.pop(context);
|
||||||
|
},
|
||||||
|
child: const Text("更新"),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}),
|
}),
|
||||||
|
|
@ -370,6 +422,7 @@ class _InvoiceInputFormState extends State<InvoiceInputForm> {
|
||||||
const SizedBox(height: 8),
|
const SizedBox(height: 8),
|
||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
|
if (_includeTax) ...[
|
||||||
const Text("消費税: "),
|
const Text("消費税: "),
|
||||||
ChoiceChip(
|
ChoiceChip(
|
||||||
label: const Text("10%"),
|
label: const Text("10%"),
|
||||||
|
|
@ -382,6 +435,8 @@ class _InvoiceInputFormState extends State<InvoiceInputForm> {
|
||||||
selected: _taxRate == 0.08,
|
selected: _taxRate == 0.08,
|
||||||
onSelected: (val) => setState(() => _taxRate = 0.08),
|
onSelected: (val) => setState(() => _taxRate = 0.08),
|
||||||
),
|
),
|
||||||
|
] else
|
||||||
|
const Text("(税別設定のため設定なし)", style: TextStyle(color: Colors.grey)),
|
||||||
const Spacer(),
|
const Spacer(),
|
||||||
Switch(
|
Switch(
|
||||||
value: _includeTax,
|
value: _includeTax,
|
||||||
|
|
@ -401,13 +456,15 @@ class _InvoiceInputFormState extends State<InvoiceInputForm> {
|
||||||
decoration: BoxDecoration(color: Colors.indigo.shade900, borderRadius: BorderRadius.circular(12)),
|
decoration: BoxDecoration(color: Colors.indigo.shade900, borderRadius: BorderRadius.circular(12)),
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
_buildSummaryRow("小計 (税抜)", "¥${fmt.format(_subTotal)}", Colors.white70),
|
_buildSummaryRow(_includeTax ? "小計 (税抜)" : "小計", "¥${fmt.format(_subTotal)}", Colors.white70),
|
||||||
|
if (_includeTax) ...[
|
||||||
if (_companyInfo?.taxDisplayMode == 'normal')
|
if (_companyInfo?.taxDisplayMode == 'normal')
|
||||||
_buildSummaryRow("消費税 (${(_taxRate * 100).toInt()}%)", "¥${fmt.format(_tax)}", Colors.white70),
|
_buildSummaryRow("消費税 (${(_taxRate * 100).toInt()}%)", "¥${fmt.format(_tax)}", Colors.white70),
|
||||||
if (_companyInfo?.taxDisplayMode == 'text_only')
|
if (_companyInfo?.taxDisplayMode == 'text_only')
|
||||||
_buildSummaryRow("消費税", "(税別)", Colors.white70),
|
_buildSummaryRow("消費税", "(税別)", Colors.white70),
|
||||||
|
],
|
||||||
const Divider(color: Colors.white24),
|
const Divider(color: Colors.white24),
|
||||||
_buildSummaryRow("合計金額", "¥${fmt.format(_total)}", Colors.white, fontSize: 24),
|
_buildSummaryRow(_includeTax ? "合計金額 (税込)" : "合計金額", "¥${fmt.format(_total)}", Colors.white, fontSize: 24),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
@ -479,8 +536,8 @@ class _InvoiceInputFormState extends State<InvoiceInputForm> {
|
||||||
Expanded(
|
Expanded(
|
||||||
child: OutlinedButton.icon(
|
child: OutlinedButton.icon(
|
||||||
onPressed: _showPreview,
|
onPressed: _showPreview,
|
||||||
icon: const Icon(Icons.remove_red_eye),
|
icon: const Icon(Icons.picture_as_pdf), // アイコン変更
|
||||||
label: const Text("仮表示"),
|
label: const Text("PDFプレビュー"), // 名称変更
|
||||||
style: OutlinedButton.styleFrom(
|
style: OutlinedButton.styleFrom(
|
||||||
padding: const EdgeInsets.symmetric(vertical: 16),
|
padding: const EdgeInsets.symmetric(vertical: 16),
|
||||||
side: const BorderSide(color: Colors.indigo),
|
side: const BorderSide(color: Colors.indigo),
|
||||||
|
|
@ -521,7 +578,31 @@ class _InvoiceInputFormState extends State<InvoiceInputForm> {
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildDraftToggle() {
|
Widget _buildDraftToggle() {
|
||||||
// ... (existing code omitted for brevity but I'll provide the new method below it)
|
return Container(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: _isDraft ? Colors.black26 : Colors.orange.shade50,
|
||||||
|
borderRadius: BorderRadius.circular(12),
|
||||||
|
border: Border.all(color: _isDraft ? Colors.orangeAccent : Colors.orange, width: 2),
|
||||||
|
),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
Icon(_isDraft ? Icons.drafts : Icons.check_circle, color: Colors.orange),
|
||||||
|
const SizedBox(width: 12),
|
||||||
|
Expanded(
|
||||||
|
child: Text(
|
||||||
|
_isDraft ? "下書き (保存のみ・PDF未生成)" : "正式発行 (PDF生成)",
|
||||||
|
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 13, color: _isDraft ? Colors.white70 : Colors.orange.shade900),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Switch(
|
||||||
|
value: _isDraft,
|
||||||
|
activeColor: Colors.orangeAccent,
|
||||||
|
onChanged: (val) => setState(() => _isDraft = val),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildSubjectSection(Color textColor) {
|
Widget _buildSubjectSection(Color textColor) {
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import 'package:sqflite/sqflite.dart';
|
||||||
import 'package:path/path.dart';
|
import 'package:path/path.dart';
|
||||||
|
|
||||||
class DatabaseHelper {
|
class DatabaseHelper {
|
||||||
static const _databaseVersion = 12;
|
static const _databaseVersion = 13;
|
||||||
static final DatabaseHelper _instance = DatabaseHelper._internal();
|
static final DatabaseHelper _instance = DatabaseHelper._internal();
|
||||||
static Database? _database;
|
static Database? _database;
|
||||||
|
|
||||||
|
|
@ -94,6 +94,9 @@ class DatabaseHelper {
|
||||||
if (oldVersion < 12) {
|
if (oldVersion < 12) {
|
||||||
await db.execute('ALTER TABLE invoices ADD COLUMN subject TEXT');
|
await db.execute('ALTER TABLE invoices ADD COLUMN subject TEXT');
|
||||||
}
|
}
|
||||||
|
if (oldVersion < 13) {
|
||||||
|
await db.execute('ALTER TABLE company_info ADD COLUMN registration_number TEXT');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _onCreate(Database db, int version) async {
|
Future<void> _onCreate(Database db, int version) async {
|
||||||
|
|
@ -193,7 +196,8 @@ class DatabaseHelper {
|
||||||
tel TEXT,
|
tel TEXT,
|
||||||
default_tax_rate REAL DEFAULT 0.10,
|
default_tax_rate REAL DEFAULT 0.10,
|
||||||
seal_path TEXT,
|
seal_path TEXT,
|
||||||
tax_display_mode TEXT DEFAULT "normal"
|
tax_display_mode TEXT DEFAULT "normal",
|
||||||
|
registration_number TEXT
|
||||||
)
|
)
|
||||||
''');
|
''');
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -96,6 +96,8 @@ Future<pw.Document> buildInvoiceDocument(Invoice invoice) async {
|
||||||
if (companyInfo.zipCode != null) pw.Text("〒${companyInfo.zipCode}"),
|
if (companyInfo.zipCode != null) pw.Text("〒${companyInfo.zipCode}"),
|
||||||
if (companyInfo.address != null) pw.Text(companyInfo.address!),
|
if (companyInfo.address != null) pw.Text(companyInfo.address!),
|
||||||
if (companyInfo.tel != null) pw.Text("TEL: ${companyInfo.tel}"),
|
if (companyInfo.tel != null) pw.Text("TEL: ${companyInfo.tel}"),
|
||||||
|
if (companyInfo.registrationNumber != null && companyInfo.registrationNumber!.isNotEmpty)
|
||||||
|
pw.Text("登録番号: ${companyInfo.registrationNumber!}", style: const pw.TextStyle(fontSize: 10)),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
if (sealImage != null)
|
if (sealImage != null)
|
||||||
|
|
@ -256,7 +258,20 @@ Future<String?> generateInvoicePdf(Invoice invoice) async {
|
||||||
final String subjectStr = invoice.subject?.isNotEmpty == true ? "_${invoice.subject}" : "";
|
final String subjectStr = invoice.subject?.isNotEmpty == true ? "_${invoice.subject}" : "";
|
||||||
|
|
||||||
// {日付}({タイプ}){顧客名}_{案件}_{金額}_{HASH下8桁}.pdf
|
// {日付}({タイプ}){顧客名}_{案件}_{金額}_{HASH下8桁}.pdf
|
||||||
String fileName = "${dateStr}(${invoice.documentTypeName})${invoice.customerNameForDisplay}${subjectStr}_${amountStr}円_$hash.pdf";
|
// 顧客名から敬称を除去
|
||||||
|
String safeCustomerName = invoice.customerNameForDisplay
|
||||||
|
.replaceAll('株式会社', '')
|
||||||
|
.replaceAll('(株)', '')
|
||||||
|
.replaceAll('(株)', '')
|
||||||
|
.replaceAll('有限会社', '')
|
||||||
|
.replaceAll('(有)', '')
|
||||||
|
.replaceAll('(有)', '')
|
||||||
|
.replaceAll('合同会社', '')
|
||||||
|
.replaceAll('(同)', '')
|
||||||
|
.replaceAll('(同)', '')
|
||||||
|
.trim();
|
||||||
|
|
||||||
|
String fileName = "${dateStr}(${invoice.documentTypeName})${safeCustomerName}${subjectStr}_${amountStr}円_$hash.pdf";
|
||||||
|
|
||||||
final directory = await getExternalStorageDirectory();
|
final directory = await getExternalStorageDirectory();
|
||||||
if (directory == null) return null;
|
if (directory == null) return null;
|
||||||
|
|
|
||||||
19
目標.md
19
目標.md
|
|
@ -56,4 +56,23 @@
|
||||||
20260214(請求書)佐々木製作所_10,000円_12345678.pdf
|
20260214(請求書)佐々木製作所_10,000円_12345678.pdf
|
||||||
明細欄にはmarkdown的要素が使える様に、簡単なものが欲しい。
|
明細欄にはmarkdown的要素が使える様に、簡単なものが欲しい。
|
||||||
インデントや箇条書き、太字など。問題はodooとの連携と型番。
|
インデントや箇条書き、太字など。問題はodooとの連携と型番。
|
||||||
|
+ 編集画面にタイトルが2行出るようになった
|
||||||
|
+ 配色でバックと文字が同系色になり見えなくなる事がある
|
||||||
|
+ 「仮表示」は「PDFプレビュー」に名称変更
|
||||||
|
+ PDFに自社情報が反映されない T番号が有る場合はT番号をPDFに記載する
|
||||||
|
+ 一覧表示する時はキーボードに隠れる部分があるのでその分余白を表示する
|
||||||
|
+ 一覧表示・検索の時にも左上には戻る矢印が必須
|
||||||
|
+ 値引きも商品とするか悩んでいます
|
||||||
|
+ 税別の場合は編集画面に消費税項目編集部分は表示しない
|
||||||
|
+ 合計金額部分も税別の時は表示を専用に切り替える
|
||||||
|
+ 仮表示(PDFプレビューに改名)は何度でも実行可能にする
|
||||||
|
+ 伝票入力画面で行の編集が可能にする
|
||||||
|
+ 顧客マスター呼び出しボタンが請求先マスターになっているのを修正
|
||||||
|
+ アンロックのスライドの右端が画面外にはみ出している
|
||||||
|
+ 編集したのを保存すると沢山伝票が増え続ける
|
||||||
|
+ 商品マスターにはグルーピング機能を追加する(商品を選択すると芋蔓式にインデントした商品が引用される)
|
||||||
|
+ 顧客マスターにはメールアドレスが必要(PDFを送信するから)
|
||||||
|
+ ファイル名には株式会社や有限会社は除去して社名だけを引用する
|
||||||
|
+ 伝票を新規発行する時は顧客名から引用できる伝票を表示し選択して引用する機能を実装する
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue