Merge branch 'develop'

This commit is contained in:
Hillel Coren 2024-01-30 18:21:49 +02:00
commit 423ec923c3
7 changed files with 41 additions and 29 deletions

View File

@ -501,6 +501,10 @@ abstract class PaymentEntity extends Object
bool get isOnline => companyGatewayId.isNotEmpty; bool get isOnline => companyGatewayId.isNotEmpty;
double get convertedExchangeRate => exchangeRate == 0 ? 1 : exchangeRate;
double get convertedAmount => completedAmount * convertedExchangeRate;
bool get isCompletedOrPartiallyRefunded => [ bool get isCompletedOrPartiallyRefunded => [
kPaymentStatusCompleted, kPaymentStatusCompleted,
kPaymentStatusPartiallyRefunded kPaymentStatusPartiallyRefunded

View File

@ -1,15 +1,12 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:flutter_redux/flutter_redux.dart';
import 'package:flutter_styled_toast/flutter_styled_toast.dart'; import 'package:flutter_styled_toast/flutter_styled_toast.dart';
import 'package:invoiceninja_flutter/data/models/client_model.dart'; import 'package:invoiceninja_flutter/data/models/client_model.dart';
import 'package:invoiceninja_flutter/redux/app/app_state.dart';
import 'package:invoiceninja_flutter/ui/app/icon_text.dart'; import 'package:invoiceninja_flutter/ui/app/icon_text.dart';
import 'package:invoiceninja_flutter/utils/localization.dart'; import 'package:invoiceninja_flutter/utils/localization.dart';
import 'package:url_launcher/url_launcher.dart'; import 'package:url_launcher/url_launcher.dart';
enum PortalLinkStyle { enum PortalLinkStyle {
icons,
buttons, buttons,
dropdown, dropdown,
} }
@ -30,9 +27,6 @@ class PortalLinks extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final store = StoreProvider.of<AppState>(context);
final state = store.state;
final prefState = state.prefState;
final localization = AppLocalization.of(context); final localization = AppLocalization.of(context);
var viewLinkWithHash = viewLink; var viewLinkWithHash = viewLink;
@ -49,23 +43,7 @@ class PortalLinks extends StatelessWidget {
showToast(localization!.copiedToClipboard.replaceFirst(':value ', '')); showToast(localization!.copiedToClipboard.replaceFirst(':value ', ''));
}; };
if (style == PortalLinkStyle.icons) { if (style == PortalLinkStyle.dropdown) {
return Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
IconButton(
onPressed: viewLinkPressed,
icon: Icon(Icons.open_in_new),
tooltip: prefState.enableTooltips ? localization!.viewPortal : '',
),
IconButton(
onPressed: copyLinkPressed,
icon: Icon(Icons.copy),
tooltip: prefState.enableTooltips ? localization!.copyLink : '',
),
],
);
} else if (style == PortalLinkStyle.dropdown) {
return PopupMenuButton<String>( return PopupMenuButton<String>(
itemBuilder: (BuildContext context) => [ itemBuilder: (BuildContext context) => [
PopupMenuItem( PopupMenuItem(

View File

@ -393,7 +393,7 @@ class _ClientViewFullwidthState extends State<ClientViewFullwidth>
viewLink: contact.silentLink, viewLink: contact.silentLink,
copyLink: contact.link, copyLink: contact.link,
client: client, client: client,
style: PortalLinkStyle.icons, style: PortalLinkStyle.buttons,
), ),
SizedBox(height: 16), SizedBox(height: 16),
] else ] else

View File

@ -80,7 +80,7 @@ class PaymentEditVM {
onSavePressed: (BuildContext context) { onSavePressed: (BuildContext context) {
Debouncer.runOnComplete(() { Debouncer.runOnComplete(() {
final payment = store.state.paymentUIState.editing!; final payment = store.state.paymentUIState.editing!;
final localization = navigatorKey.localization; final localization = navigatorKey.localization!;
final navigator = navigatorKey.currentState; final navigator = navigatorKey.currentState;
double amount = 0; double amount = 0;
payment.invoices.forEach((invoice) => amount += invoice.amount); payment.invoices.forEach((invoice) => amount += invoice.amount);
@ -89,17 +89,28 @@ class PaymentEditVM {
showDialog<ErrorDialog>( showDialog<ErrorDialog>(
context: navigatorKey.currentContext!, context: navigatorKey.currentContext!,
builder: (BuildContext context) { builder: (BuildContext context) {
return ErrorDialog(localization!.creditPaymentError); return ErrorDialog(localization.creditPaymentError);
});
return null;
} else if (!state.company.enableApplyingPayments &&
payment.invoices.isEmpty &&
payment.credits.isEmpty) {
showDialog<ErrorDialog>(
context: navigatorKey.currentContext!,
builder: (BuildContext context) {
return ErrorDialog(
localization.pleaseSelectAnInvoiceOrCredit);
}); });
return null; return null;
} }
final Completer<PaymentEntity> completer = Completer<PaymentEntity>(); final Completer<PaymentEntity> completer = Completer<PaymentEntity>();
store.dispatch( store.dispatch(
SavePaymentRequest(completer: completer, payment: payment)); SavePaymentRequest(completer: completer, payment: payment));
return completer.future.then((savedPayment) { return completer.future.then((savedPayment) {
showToast(payment.isNew showToast(payment.isNew
? localization!.createdPayment ? localization.createdPayment
: localization!.updatedPayment); : localization.updatedPayment);
if (state.prefState.isMobile) { if (state.prefState.isMobile) {
store.dispatch(UpdateCurrentRoute(PaymentViewScreen.route)); store.dispatch(UpdateCurrentRoute(PaymentViewScreen.route));
if (payment.isNew) { if (payment.isNew) {

View File

@ -36,6 +36,7 @@ enum ProfitAndLossReportFields {
currency, currency,
transaction_reference, transaction_reference,
record_state, record_state,
converted_amount,
} }
var memoizedProfitAndLossReport = memo9(( var memoizedProfitAndLossReport = memo9((
@ -179,6 +180,9 @@ ReportResult profitAndLossReport(
value = AppLocalization.of(navigatorKey.currentContext!)! value = AppLocalization.of(navigatorKey.currentContext!)!
.lookup(payment.entityState); .lookup(payment.entityState);
break; break;
case ProfitAndLossReportFields.converted_amount:
value = payment.convertedAmount;
break;
} }
if (!ReportResult.matchField( if (!ReportResult.matchField(
@ -194,6 +198,9 @@ ReportResult profitAndLossReport(
row.add(payment.getReportEntityType()); row.add(payment.getReportEntityType());
} else if (value.runtimeType == bool) { } else if (value.runtimeType == bool) {
row.add(payment.getReportBool(value: value)); row.add(payment.getReportBool(value: value));
} else if (column == ProfitAndLossReportFields.converted_amount) {
row.add(payment.getReportDouble(
value: value, currencyId: userCompany.company.currencyId));
} else if (value.runtimeType == double || value.runtimeType == int) { } else if (value.runtimeType == double || value.runtimeType == int) {
row.add(payment.getReportDouble( row.add(payment.getReportDouble(
value: value, currencyId: client.currencyId)); value: value, currencyId: client.currencyId));
@ -286,6 +293,9 @@ ReportResult profitAndLossReport(
value = AppLocalization.of(navigatorKey.currentContext!)! value = AppLocalization.of(navigatorKey.currentContext!)!
.lookup(expense.entityState); .lookup(expense.entityState);
break; break;
case ProfitAndLossReportFields.converted_amount:
value = expense.convertedAmount;
break;
} }
if (!ReportResult.matchField( if (!ReportResult.matchField(
@ -301,6 +311,9 @@ ReportResult profitAndLossReport(
row.add(expense.getReportEntityType()); row.add(expense.getReportEntityType());
} else if (value.runtimeType == bool) { } else if (value.runtimeType == bool) {
row.add(expense.getReportBool(value: value)); row.add(expense.getReportBool(value: value));
} else if (column == ProfitAndLossReportFields.converted_amount) {
row.add(expense.getReportDouble(
value: value, currencyId: userCompany.company.currencyId));
} else if (value.runtimeType == double || value.runtimeType == int) { } else if (value.runtimeType == double || value.runtimeType == int) {
row.add(expense.getReportDouble( row.add(expense.getReportDouble(
value: value, currencyId: expense.currencyId)); value: value, currencyId: expense.currencyId));

View File

@ -299,7 +299,7 @@ class _VendorViewFullwidthState extends State<VendorViewFullwidth>
viewLink: contact.silentLink, viewLink: contact.silentLink,
copyLink: contact.link, copyLink: contact.link,
client: null, client: null,
style: PortalLinkStyle.icons, style: PortalLinkStyle.buttons,
), ),
SizedBox(height: 16), SizedBox(height: 16),
] else ] else

View File

@ -18,6 +18,8 @@ mixin LocalizationsProvider on LocaleCodeAware {
static final Map<String, Map<String, String>> _localizedValues = { static final Map<String, Map<String, String>> _localizedValues = {
'en': { 'en': {
// STARTER: lang key - do not remove comment // STARTER: lang key - do not remove comment
'please_select_an_invoice_or_credit':
'Please select an invoice or credit',
'mobile_version': 'Mobile Version', 'mobile_version': 'Mobile Version',
'venmo': 'Venmo', 'venmo': 'Venmo',
'mercado_pago': 'Mercado Pago', 'mercado_pago': 'Mercado Pago',
@ -114273,6 +114275,10 @@ mixin LocalizationsProvider on LocaleCodeAware {
_localizedValues[localeCode]!['mobile_version'] ?? _localizedValues[localeCode]!['mobile_version'] ??
_localizedValues['en']!['mobile_version']!; _localizedValues['en']!['mobile_version']!;
String get pleaseSelectAnInvoiceOrCredit =>
_localizedValues[localeCode]!['please_select_an_invoice_or_credit'] ??
_localizedValues['en']!['please_select_an_invoice_or_credit']!;
// STARTER: lang field - do not remove comment // STARTER: lang field - do not remove comment
String lookup(String? key) { String lookup(String? key) {