Vendors
This commit is contained in:
parent
4b0398a040
commit
16921e4e6e
|
|
@ -441,7 +441,8 @@ abstract class ExpenseEntity extends Object
|
|||
}
|
||||
|
||||
bool isBetween(String startDate, String endDate) {
|
||||
return startDate.compareTo(date) <= 0 && endDate.compareTo(date) >= 0;
|
||||
return (startDate ?? '').compareTo(date ?? '') <= 0 &&
|
||||
(endDate ?? '').compareTo(date ?? '') >= 0;
|
||||
}
|
||||
|
||||
@override
|
||||
|
|
|
|||
|
|
@ -55,6 +55,7 @@ class VendorFields {
|
|||
static const String countryId = 'country_id';
|
||||
static const String phone = 'phone';
|
||||
static const String privateNotes = 'private_notes';
|
||||
static const String publicNotes = 'public_notes';
|
||||
static const String website = 'website';
|
||||
static const String vatNumber = 'vat_number';
|
||||
static const String idNumber = 'id_number';
|
||||
|
|
@ -86,6 +87,7 @@ abstract class VendorEntity extends Object
|
|||
countryId: '',
|
||||
phone: '',
|
||||
privateNotes: '',
|
||||
publicNotes: '',
|
||||
website: '',
|
||||
vatNumber: '',
|
||||
idNumber: '',
|
||||
|
|
@ -147,6 +149,9 @@ abstract class VendorEntity extends Object
|
|||
@BuiltValueField(wireName: 'private_notes')
|
||||
String get privateNotes;
|
||||
|
||||
@BuiltValueField(wireName: 'public_notes')
|
||||
String get publicNotes;
|
||||
|
||||
String get website;
|
||||
|
||||
@nullable // TODO remove this
|
||||
|
|
|
|||
|
|
@ -137,6 +137,9 @@ class _$VendorEntitySerializer implements StructuredSerializer<VendorEntity> {
|
|||
'private_notes',
|
||||
serializers.serialize(object.privateNotes,
|
||||
specifiedType: const FullType(String)),
|
||||
'public_notes',
|
||||
serializers.serialize(object.publicNotes,
|
||||
specifiedType: const FullType(String)),
|
||||
'website',
|
||||
serializers.serialize(object.website,
|
||||
specifiedType: const FullType(String)),
|
||||
|
|
@ -264,6 +267,10 @@ class _$VendorEntitySerializer implements StructuredSerializer<VendorEntity> {
|
|||
result.privateNotes = serializers.deserialize(value,
|
||||
specifiedType: const FullType(String)) as String;
|
||||
break;
|
||||
case 'public_notes':
|
||||
result.publicNotes = serializers.deserialize(value,
|
||||
specifiedType: const FullType(String)) as String;
|
||||
break;
|
||||
case 'website':
|
||||
result.website = serializers.deserialize(value,
|
||||
specifiedType: const FullType(String)) as String;
|
||||
|
|
@ -702,6 +709,8 @@ class _$VendorEntity extends VendorEntity {
|
|||
@override
|
||||
final String privateNotes;
|
||||
@override
|
||||
final String publicNotes;
|
||||
@override
|
||||
final String website;
|
||||
@override
|
||||
final String number;
|
||||
|
|
@ -753,6 +762,7 @@ class _$VendorEntity extends VendorEntity {
|
|||
this.countryId,
|
||||
this.phone,
|
||||
this.privateNotes,
|
||||
this.publicNotes,
|
||||
this.website,
|
||||
this.number,
|
||||
this.vatNumber,
|
||||
|
|
@ -800,6 +810,9 @@ class _$VendorEntity extends VendorEntity {
|
|||
if (privateNotes == null) {
|
||||
throw new BuiltValueNullFieldError('VendorEntity', 'privateNotes');
|
||||
}
|
||||
if (publicNotes == null) {
|
||||
throw new BuiltValueNullFieldError('VendorEntity', 'publicNotes');
|
||||
}
|
||||
if (website == null) {
|
||||
throw new BuiltValueNullFieldError('VendorEntity', 'website');
|
||||
}
|
||||
|
|
@ -861,6 +874,7 @@ class _$VendorEntity extends VendorEntity {
|
|||
countryId == other.countryId &&
|
||||
phone == other.phone &&
|
||||
privateNotes == other.privateNotes &&
|
||||
publicNotes == other.publicNotes &&
|
||||
website == other.website &&
|
||||
number == other.number &&
|
||||
vatNumber == other.vatNumber &&
|
||||
|
|
@ -903,7 +917,7 @@ class _$VendorEntity extends VendorEntity {
|
|||
$jc(
|
||||
$jc(
|
||||
$jc(
|
||||
$jc($jc($jc($jc($jc($jc($jc($jc($jc($jc(0, name.hashCode), address1.hashCode), address2.hashCode), city.hashCode), state.hashCode), postalCode.hashCode), countryId.hashCode), phone.hashCode), privateNotes.hashCode),
|
||||
$jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc(0, name.hashCode), address1.hashCode), address2.hashCode), city.hashCode), state.hashCode), postalCode.hashCode), countryId.hashCode), phone.hashCode), privateNotes.hashCode), publicNotes.hashCode),
|
||||
website.hashCode),
|
||||
number.hashCode),
|
||||
vatNumber.hashCode),
|
||||
|
|
@ -937,6 +951,7 @@ class _$VendorEntity extends VendorEntity {
|
|||
..add('countryId', countryId)
|
||||
..add('phone', phone)
|
||||
..add('privateNotes', privateNotes)
|
||||
..add('publicNotes', publicNotes)
|
||||
..add('website', website)
|
||||
..add('number', number)
|
||||
..add('vatNumber', vatNumber)
|
||||
|
|
@ -1000,6 +1015,10 @@ class VendorEntityBuilder
|
|||
String get privateNotes => _$this._privateNotes;
|
||||
set privateNotes(String privateNotes) => _$this._privateNotes = privateNotes;
|
||||
|
||||
String _publicNotes;
|
||||
String get publicNotes => _$this._publicNotes;
|
||||
set publicNotes(String publicNotes) => _$this._publicNotes = publicNotes;
|
||||
|
||||
String _website;
|
||||
String get website => _$this._website;
|
||||
set website(String website) => _$this._website = website;
|
||||
|
|
@ -1095,6 +1114,7 @@ class VendorEntityBuilder
|
|||
_countryId = _$v.countryId;
|
||||
_phone = _$v.phone;
|
||||
_privateNotes = _$v.privateNotes;
|
||||
_publicNotes = _$v.publicNotes;
|
||||
_website = _$v.website;
|
||||
_number = _$v.number;
|
||||
_vatNumber = _$v.vatNumber;
|
||||
|
|
@ -1147,6 +1167,7 @@ class VendorEntityBuilder
|
|||
countryId: countryId,
|
||||
phone: phone,
|
||||
privateNotes: privateNotes,
|
||||
publicNotes: publicNotes,
|
||||
website: website,
|
||||
number: number,
|
||||
vatNumber: vatNumber,
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
class IconMessage extends StatelessWidget {
|
||||
const IconMessage(this.text);
|
||||
const IconMessage(this.text, {this.iconData});
|
||||
final String text;
|
||||
final IconData iconData;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
|
@ -13,7 +14,7 @@ class IconMessage extends StatelessWidget {
|
|||
child: Row(
|
||||
children: <Widget>[
|
||||
Icon(
|
||||
Icons.info_outline,
|
||||
iconData ?? Icons.info_outline,
|
||||
size: 18.0,
|
||||
color: Colors.white,
|
||||
),
|
||||
|
|
|
|||
|
|
@ -119,9 +119,10 @@ class ClientOverview extends StatelessWidget {
|
|||
formatNumber(client.balance, context, clientId: client.id),
|
||||
),
|
||||
ListDivider(),
|
||||
client.privateNotes != null && client.privateNotes.isNotEmpty
|
||||
? IconMessage(client.privateNotes)
|
||||
: Container(),
|
||||
if ((client.privateNotes ?? '').isNotEmpty) ...[
|
||||
IconMessage(client.privateNotes, iconData: Icons.lock),
|
||||
ListDivider()
|
||||
],
|
||||
if (client.hasGroup)
|
||||
EntityListTile(
|
||||
entity: group,
|
||||
|
|
@ -244,6 +245,10 @@ class ClientOverview extends StatelessWidget {
|
|||
memoizedExpenseStatsForClient(client.id, state.expenseState.map)
|
||||
.present(localization.active, localization.archived),
|
||||
),
|
||||
if ((client.publicNotes ?? '').isNotEmpty) ...[
|
||||
IconMessage(client.publicNotes),
|
||||
ListDivider()
|
||||
],
|
||||
],
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@ import 'package:flutter/foundation.dart';
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:image_picker/image_picker.dart';
|
||||
import 'package:invoiceninja_flutter/ui/app/view_scaffold.dart';
|
||||
import 'package:invoiceninja_flutter/ui/expense/view/expense_view_details.dart';
|
||||
import 'package:invoiceninja_flutter/ui/expense/view/expense_view_documents.dart';
|
||||
import 'package:invoiceninja_flutter/ui/expense/view/expense_view_vm.dart';
|
||||
import 'package:invoiceninja_flutter/ui/expense/view/expense_view_overview.dart';
|
||||
|
|
@ -31,7 +30,7 @@ class _ExpenseViewState extends State<ExpenseView>
|
|||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_controller = TabController(vsync: this, length: 3);
|
||||
_controller = TabController(vsync: this, length: 2);
|
||||
}
|
||||
|
||||
@override
|
||||
|
|
@ -55,9 +54,6 @@ class _ExpenseViewState extends State<ExpenseView>
|
|||
Tab(
|
||||
text: localization.overview,
|
||||
),
|
||||
Tab(
|
||||
text: localization.details,
|
||||
),
|
||||
Tab(
|
||||
text: expense.documents.isEmpty
|
||||
? localization.documents
|
||||
|
|
@ -73,10 +69,6 @@ class _ExpenseViewState extends State<ExpenseView>
|
|||
onRefresh: () => viewModel.onRefreshed(context),
|
||||
child: ExpenseOverview(viewModel: viewModel),
|
||||
),
|
||||
RefreshIndicator(
|
||||
onRefresh: () => viewModel.onRefreshed(context),
|
||||
child: ExpenseViewDetails(expense: viewModel.expense),
|
||||
),
|
||||
RefreshIndicator(
|
||||
onRefresh: () => viewModel.onRefreshed(context),
|
||||
child: ExpenseViewDocuments(
|
||||
|
|
|
|||
|
|
@ -1,75 +0,0 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_redux/flutter_redux.dart';
|
||||
import 'package:invoiceninja_flutter/data/models/models.dart';
|
||||
import 'package:invoiceninja_flutter/redux/app/app_state.dart';
|
||||
import 'package:invoiceninja_flutter/ui/app/FieldGrid.dart';
|
||||
import 'package:invoiceninja_flutter/ui/app/icon_message.dart';
|
||||
import 'package:invoiceninja_flutter/utils/formatting.dart';
|
||||
import 'package:invoiceninja_flutter/utils/localization.dart';
|
||||
|
||||
class ExpenseViewDetails extends StatefulWidget {
|
||||
const ExpenseViewDetails({this.expense});
|
||||
|
||||
final ExpenseEntity expense;
|
||||
|
||||
@override
|
||||
_ExpenseViewDetailsState createState() => _ExpenseViewDetailsState();
|
||||
}
|
||||
|
||||
class _ExpenseViewDetailsState extends State<ExpenseViewDetails> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final state = StoreProvider.of<AppState>(context).state;
|
||||
final localization = AppLocalization.of(context);
|
||||
final expense = widget.expense;
|
||||
|
||||
List<Widget> _buildDetailsList() {
|
||||
String tax = '';
|
||||
if (expense.taxName1.isNotEmpty) {
|
||||
tax += formatNumber(expense.taxRate1, context,
|
||||
formatNumberType: FormatNumberType.percent) +
|
||||
' ' +
|
||||
expense.taxName1;
|
||||
}
|
||||
if (expense.taxName2.isNotEmpty) {
|
||||
tax += ' ' +
|
||||
formatNumber(expense.taxRate2, context,
|
||||
formatNumberType: FormatNumberType.percent) +
|
||||
' ' +
|
||||
expense.taxName2;
|
||||
}
|
||||
|
||||
final fields = <String, String>{
|
||||
localization.amount: formatNumber(expense.amount, context,
|
||||
currencyId: expense.expenseCurrencyId),
|
||||
localization.tax: tax,
|
||||
localization.paymentType:
|
||||
state.staticState.paymentTypeMap[expense.paymentTypeId]?.name,
|
||||
localization.paymentDate: formatDate(expense.paymentDate, context),
|
||||
localization.transactionReference: expense.transactionReference,
|
||||
localization.exchangeRate: expense.isConverted
|
||||
? formatNumber(expense.exchangeRate, context,
|
||||
formatNumberType: FormatNumberType.double)
|
||||
: null,
|
||||
localization.currency: expense.isConverted
|
||||
? state.staticState.currencyMap[expense.invoiceCurrencyId]?.name
|
||||
: null,
|
||||
};
|
||||
|
||||
final listTiles = <Widget>[
|
||||
FieldGrid(fields),
|
||||
Divider(
|
||||
height: 1.0,
|
||||
),
|
||||
if (expense.publicNotes != null && expense.publicNotes.isNotEmpty)
|
||||
IconMessage(expense.publicNotes),
|
||||
];
|
||||
|
||||
return listTiles;
|
||||
}
|
||||
|
||||
return ListView(
|
||||
children: _buildDetailsList(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -3,6 +3,7 @@ import 'package:invoiceninja_flutter/data/models/entities.dart';
|
|||
import 'package:invoiceninja_flutter/ui/app/FieldGrid.dart';
|
||||
import 'package:invoiceninja_flutter/ui/app/entities/entity_state_title.dart';
|
||||
import 'package:invoiceninja_flutter/ui/app/entity_header.dart';
|
||||
import 'package:invoiceninja_flutter/ui/app/lists/list_divider.dart';
|
||||
import 'package:invoiceninja_flutter/ui/expense/view/expense_view_vm.dart';
|
||||
import 'package:invoiceninja_flutter/utils/formatting.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
|
@ -49,6 +50,44 @@ class ExpenseOverview extends StatelessWidget {
|
|||
value: expense.customValue2);
|
||||
}
|
||||
|
||||
List<Widget> _buildDetailsList() {
|
||||
String tax = '';
|
||||
if (expense.taxName1.isNotEmpty) {
|
||||
tax += formatNumber(expense.taxRate1, context,
|
||||
formatNumberType: FormatNumberType.percent) +
|
||||
' ' +
|
||||
expense.taxName1;
|
||||
}
|
||||
if (expense.taxName2.isNotEmpty) {
|
||||
tax += ' ' +
|
||||
formatNumber(expense.taxRate2, context,
|
||||
formatNumberType: FormatNumberType.percent) +
|
||||
' ' +
|
||||
expense.taxName2;
|
||||
}
|
||||
|
||||
final fields = <String, String>{
|
||||
localization.tax: tax,
|
||||
localization.paymentType:
|
||||
state.staticState.paymentTypeMap[expense.paymentTypeId]?.name,
|
||||
localization.paymentDate: formatDate(expense.paymentDate, context),
|
||||
localization.transactionReference: expense.transactionReference,
|
||||
localization.exchangeRate: expense.isConverted
|
||||
? formatNumber(expense.exchangeRate, context,
|
||||
formatNumberType: FormatNumberType.double)
|
||||
: null,
|
||||
localization.currency: expense.isConverted
|
||||
? state.staticState.currencyMap[expense.invoiceCurrencyId]?.name
|
||||
: null,
|
||||
};
|
||||
|
||||
final listTiles = <Widget>[
|
||||
FieldGrid(fields),
|
||||
];
|
||||
|
||||
return listTiles;
|
||||
}
|
||||
|
||||
return ListView(
|
||||
children: <Widget>[
|
||||
expense.isConverted
|
||||
|
|
@ -74,13 +113,12 @@ class ExpenseOverview extends StatelessWidget {
|
|||
value: formatNumber(expense.amountWithTax, context,
|
||||
currencyId: expense.expenseCurrencyId),
|
||||
),
|
||||
expense.privateNotes != null && expense.privateNotes.isNotEmpty
|
||||
? IconMessage(expense.privateNotes)
|
||||
: Container(),
|
||||
ListDivider(),
|
||||
if ((expense.privateNotes ?? '').isNotEmpty) ...[
|
||||
IconMessage(expense.privateNotes, iconData: Icons.lock),
|
||||
],
|
||||
FieldGrid(fields),
|
||||
Divider(
|
||||
height: 1.0,
|
||||
),
|
||||
ListDivider(),
|
||||
vendor == null
|
||||
? SizedBox()
|
||||
: Material(
|
||||
|
|
@ -137,12 +175,11 @@ class ExpenseOverview extends StatelessWidget {
|
|||
context, EntityType.invoice, true),
|
||||
),
|
||||
),
|
||||
invoice == null
|
||||
? SizedBox()
|
||||
: Container(
|
||||
color: Theme.of(context).backgroundColor,
|
||||
height: 12.0,
|
||||
),
|
||||
..._buildDetailsList(),
|
||||
if ((expense.publicNotes ?? '').isNotEmpty) ...[
|
||||
IconMessage(expense.publicNotes),
|
||||
ListDivider()
|
||||
],
|
||||
],
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -104,6 +104,16 @@ class InvoiceOverview extends StatelessWidget {
|
|||
ListDivider(),
|
||||
];
|
||||
|
||||
if ((invoice.privateNotes ?? '').isNotEmpty) {
|
||||
widgets.addAll([
|
||||
IconMessage(
|
||||
invoice.privateNotes,
|
||||
iconData: Icons.lock,
|
||||
),
|
||||
ListDivider(),
|
||||
]);
|
||||
}
|
||||
|
||||
String dueDateField = InvoiceFields.dueDate;
|
||||
if (invoice.isQuote) {
|
||||
dueDateField = QuoteFields.validUntil;
|
||||
|
|
@ -282,13 +292,6 @@ class InvoiceOverview extends StatelessWidget {
|
|||
FieldGrid(fields),
|
||||
]);
|
||||
|
||||
if (invoice.privateNotes != null && invoice.privateNotes.isNotEmpty) {
|
||||
widgets.addAll([
|
||||
IconMessage(invoice.privateNotes),
|
||||
ListDivider(),
|
||||
]);
|
||||
}
|
||||
|
||||
if (invoice.lineItems.isNotEmpty) {
|
||||
invoice.lineItems.forEach((invoiceItem) {
|
||||
widgets.addAll([
|
||||
|
|
@ -385,6 +388,13 @@ class InvoiceOverview extends StatelessWidget {
|
|||
widgets.add(surchargeRow(localization.total,
|
||||
invoice.partial != 0 ? invoice.partial : invoice.calculateTotal));
|
||||
|
||||
if ((invoice.publicNotes ?? '').isNotEmpty) {
|
||||
widgets.addAll([
|
||||
ListDivider(),
|
||||
IconMessage(invoice.publicNotes),
|
||||
]);
|
||||
}
|
||||
|
||||
return ListView(
|
||||
children: widgets,
|
||||
);
|
||||
|
|
|
|||
|
|
@ -88,6 +88,10 @@ class _ProjectOverviewState extends State<ProjectOverview> {
|
|||
showSeconds: false),
|
||||
),
|
||||
ListDivider(),
|
||||
if ((project.privateNotes ?? '').isNotEmpty) ...[
|
||||
IconMessage(project.privateNotes, iconData: Icons.lock),
|
||||
ListDivider()
|
||||
],
|
||||
EntityListTile(
|
||||
entity: client,
|
||||
isFilter: widget.isFilter,
|
||||
|
|
@ -114,20 +118,17 @@ class _ProjectOverviewState extends State<ProjectOverview> {
|
|||
),
|
||||
];
|
||||
|
||||
if (project.privateNotes != null && project.privateNotes.isNotEmpty) {
|
||||
widgets.addAll([
|
||||
IconMessage(project.privateNotes),
|
||||
Container(
|
||||
color: Theme.of(context).backgroundColor,
|
||||
height: 12.0,
|
||||
),
|
||||
]);
|
||||
}
|
||||
|
||||
widgets.addAll([
|
||||
FieldGrid(fields),
|
||||
]);
|
||||
|
||||
if ((project.publicNotes ?? '').isNotEmpty) {
|
||||
widgets.addAll([
|
||||
IconMessage(project.publicNotes),
|
||||
ListDivider()
|
||||
]);
|
||||
}
|
||||
|
||||
return widgets;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ class VendorEditNotesState extends State<VendorEditNotes> {
|
|||
.forEach((dynamic controller) => controller.removeListener(_onChanged));
|
||||
|
||||
final vendor = widget.viewModel.vendor;
|
||||
//_publicNotesController.text = vendor.publicNotes;
|
||||
_publicNotesController.text = vendor.publicNotes;
|
||||
_privateNotesController.text = vendor.privateNotes;
|
||||
|
||||
_controllers
|
||||
|
|
@ -62,7 +62,7 @@ class VendorEditNotesState extends State<VendorEditNotes> {
|
|||
_debouncer.run(() {
|
||||
final viewModel = widget.viewModel;
|
||||
final vendor = viewModel.vendor.rebuild((b) => b
|
||||
//..publicNotes = _publicNotesController.text
|
||||
..publicNotes = _publicNotesController.text
|
||||
..privateNotes = _privateNotesController.text);
|
||||
if (vendor != viewModel.vendor) {
|
||||
viewModel.onChanged(vendor);
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import 'package:invoiceninja_flutter/redux/vendor/vendor_selectors.dart';
|
|||
import 'package:invoiceninja_flutter/ui/app/FieldGrid.dart';
|
||||
import 'package:invoiceninja_flutter/ui/app/entities/entity_list_tile.dart';
|
||||
import 'package:invoiceninja_flutter/ui/app/entity_header.dart';
|
||||
import 'package:invoiceninja_flutter/ui/app/lists/list_divider.dart';
|
||||
import 'package:invoiceninja_flutter/ui/vendor/view/vendor_view_vm.dart';
|
||||
import 'package:invoiceninja_flutter/utils/formatting.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
|
@ -64,13 +65,13 @@ class VendorOverview extends StatelessWidget {
|
|||
context,
|
||||
currencyId: vendor.currencyId ?? company.currencyId),
|
||||
),
|
||||
vendor.privateNotes != null && vendor.privateNotes.isNotEmpty
|
||||
? IconMessage(vendor.privateNotes)
|
||||
: Container(),
|
||||
ListDivider(),
|
||||
if ((vendor.privateNotes ?? '').isNotEmpty) ...[
|
||||
IconMessage(vendor.privateNotes, iconData: Icons.lock),
|
||||
ListDivider()
|
||||
],
|
||||
FieldGrid(fields),
|
||||
Divider(
|
||||
height: 1.0,
|
||||
),
|
||||
ListDivider(),
|
||||
EntitiesListTile(
|
||||
entity: vendor,
|
||||
title: localization.expenses,
|
||||
|
|
@ -80,6 +81,10 @@ class VendorOverview extends StatelessWidget {
|
|||
memoizedExpenseStatsForVendor(vendor.id, state.expenseState.map)
|
||||
.present(localization.active, localization.archived),
|
||||
),
|
||||
if ((vendor.publicNotes ?? '').isNotEmpty) ...[
|
||||
IconMessage(vendor.publicNotes),
|
||||
ListDivider()
|
||||
],
|
||||
],
|
||||
);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue