gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[taler-wallet-core] branch master updated: show refund info in purchase


From: gnunet
Subject: [taler-wallet-core] branch master updated: show refund info in purchase
Date: Sun, 29 May 2022 06:23:29 +0200

This is an automated email from the git hooks/post-receive script.

sebasjm pushed a commit to branch master
in repository wallet-core.

The following commit(s) were added to refs/heads/master by this push:
     new 02934046 show refund info in purchase
02934046 is described below

commit 029340469ac661bab1450b1ff4dcc6e717780e5b
Author: Sebastian <sebasjm@gmail.com>
AuthorDate: Sun May 29 01:23:15 2022 -0300

    show refund info in purchase
    
    notify refund pending with accept button on the purchase details
    better payto box
---
 packages/taler-util/src/transactionsTypes.ts       | 12 ++++
 packages/taler-util/src/walletTypes.ts             |  9 +++
 .../taler-wallet-core/src/operations/refund.ts     | 14 +++-
 .../src/operations/transactions.ts                 | 13 +++-
 packages/taler-wallet-core/src/wallet.ts           |  6 ++
 .../src/components/Part.tsx                        | 29 +++++---
 .../src/components/TransactionItem.tsx             |  2 +-
 .../src/wallet/History.stories.tsx                 |  1 +
 .../src/wallet/History.tsx                         |  2 +-
 .../src/wallet/ReserveCreated.stories.tsx          |  2 +-
 .../src/wallet/Transaction.stories.tsx             | 30 ++++++++-
 .../src/wallet/Transaction.tsx                     | 78 ++++++++++++++++++++--
 packages/taler-wallet-webextension/src/wxApi.ts    |  9 +++
 13 files changed, 183 insertions(+), 24 deletions(-)

diff --git a/packages/taler-util/src/transactionsTypes.ts 
b/packages/taler-util/src/transactionsTypes.ts
index dcaa5667..f7383f90 100644
--- a/packages/taler-util/src/transactionsTypes.ts
+++ b/packages/taler-util/src/transactionsTypes.ts
@@ -244,6 +244,11 @@ export interface TransactionPayment extends 
TransactionCommon {
    * Amount pending to be picked up
    */
   refundPending: AmountString | undefined;
+
+  /**
+   * Reference to applied refunds
+   */
+  refunds: RefundInfoShort[];
 }
 
 export interface OrderShortInfo {
@@ -305,6 +310,13 @@ export interface OrderShortInfo {
   fulfillmentMessage_i18n?: InternationalizedString;
 }
 
+export interface RefundInfoShort {
+  transactionId: string,
+  timestamp: TalerProtocolTimestamp,
+  amountEffective: AmountString,
+  amountRaw: AmountString,
+}
+
 export interface TransactionRefund extends TransactionCommon {
   type: TransactionType.Refund;
 
diff --git a/packages/taler-util/src/walletTypes.ts 
b/packages/taler-util/src/walletTypes.ts
index fa884c41..00a48986 100644
--- a/packages/taler-util/src/walletTypes.ts
+++ b/packages/taler-util/src/walletTypes.ts
@@ -799,6 +799,15 @@ export const codecForApplyRefundRequest = (): 
Codec<ApplyRefundRequest> =>
     .property("talerRefundUri", codecForString())
     .build("ApplyRefundRequest");
 
+export interface ApplyRefundFromPurchaseIdRequest {
+  purchaseId: string;
+}
+
+export const codecForApplyRefundFromPurchaseIdRequest = (): 
Codec<ApplyRefundFromPurchaseIdRequest> =>
+  buildCodecForObject<ApplyRefundFromPurchaseIdRequest>()
+    .property("purchaseId", codecForString())
+    .build("ApplyRefundFromPurchaseIdRequest");
+
 export interface GetWithdrawalDetailsForUriRequest {
   talerWithdrawUri: string;
   restrictAge?: number;
diff --git a/packages/taler-wallet-core/src/operations/refund.ts 
b/packages/taler-wallet-core/src/operations/refund.ts
index 186fbf7d..28a92286 100644
--- a/packages/taler-wallet-core/src/operations/refund.ts
+++ b/packages/taler-wallet-core/src/operations/refund.ts
@@ -573,7 +573,7 @@ export async function applyRefund(
     throw Error("invalid refund URI");
   }
 
-  let purchase = await ws.db
+  const purchase = await ws.db
     .mktx((x) => ({
       purchases: x.purchases,
     }))
@@ -590,7 +590,15 @@ export async function applyRefund(
     );
   }
 
-  const proposalId = purchase.proposalId;
+  return applyRefundFromPurchaseId(ws, purchase.proposalId)
+}
+
+export async function applyRefundFromPurchaseId(
+  ws: InternalWalletState,
+  proposalId: string,
+): Promise<ApplyRefundResponse> {
+
+  logger.trace("applying refund for purchase", proposalId);
 
   logger.info("processing purchase for refund");
   const success = await ws.db
@@ -620,7 +628,7 @@ export async function applyRefund(
     });
   }
 
-  purchase = await ws.db
+  const purchase = await ws.db
     .mktx((x) => ({
       purchases: x.purchases,
     }))
diff --git a/packages/taler-wallet-core/src/operations/transactions.ts 
b/packages/taler-wallet-core/src/operations/transactions.ts
index 87b109d9..db282bb6 100644
--- a/packages/taler-wallet-core/src/operations/transactions.ts
+++ b/packages/taler-wallet-core/src/operations/transactions.ts
@@ -24,6 +24,7 @@ import {
   Logger,
   OrderShortInfo,
   PaymentStatus,
+  RefundInfoShort,
   Transaction,
   TransactionsRequest,
   TransactionsResponse,
@@ -306,6 +307,7 @@ export async function getTransactions(
 
           let totalRefundRaw = Amounts.getZero(contractData.amount.currency);
           let totalRefundEffective = 
Amounts.getZero(contractData.amount.currency);
+          const refunds: RefundInfoShort[] = []
 
           for (const groupKey of refundGroupKeys.values()) {
             const refundTombstoneId = makeEventId(
@@ -345,6 +347,13 @@ export async function getTransactions(
                     refund.totalRefreshCostBound,
                   ).amount,
                 ).amount;
+
+                refunds.push({
+                  transactionId: refundTransactionId,
+                  timestamp: r0.obtainedTime,
+                  amountEffective: Amounts.stringify(amountEffective),
+                  amountRaw: Amounts.stringify(amountRaw),
+                })
               }
             }
             if (!r0) {
@@ -353,7 +362,6 @@ export async function getTransactions(
 
             totalRefundRaw = Amounts.add(totalRefundRaw, amountRaw).amount;
             totalRefundEffective = Amounts.add(totalRefundEffective, 
amountEffective).amount;
-
             transactions.push({
               type: TransactionType.Refund,
               info,
@@ -382,10 +390,11 @@ export async function getTransactions(
             pending:
               !pr.timestampFirstSuccessfulPay &&
               pr.abortStatus === AbortStatus.None,
+            refunds,
             timestamp: pr.timestampAccept,
             transactionId: paymentTransactionId,
             proposalId: pr.proposalId,
-            info: info,
+            info,
             frozen: pr.payFrozen ?? false,
             ...(err ? { error: err } : {}),
           });
diff --git a/packages/taler-wallet-core/src/wallet.ts 
b/packages/taler-wallet-core/src/wallet.ts
index ffceec38..689e45f3 100644
--- a/packages/taler-wallet-core/src/wallet.ts
+++ b/packages/taler-wallet-core/src/wallet.ts
@@ -33,6 +33,7 @@ import {
   codecForAcceptTipRequest,
   codecForAddExchangeRequest,
   codecForAny,
+  codecForApplyRefundFromPurchaseIdRequest,
   codecForApplyRefundRequest,
   codecForConfirmPayRequest,
   codecForCreateDepositGroupRequest,
@@ -145,6 +146,7 @@ import {
 import {
   abortFailedPayWithRefund,
   applyRefund,
+  applyRefundFromPurchaseId,
   prepareRefund,
   processPurchaseQueryRefund
 } from "./operations/refund.js";
@@ -839,6 +841,10 @@ async function dispatchRequestInternal(
       const req = codecForApplyRefundRequest().decode(payload);
       return await applyRefund(ws, req.talerRefundUri);
     }
+    case "applyRefundFromPurchaseId": {
+      const req = codecForApplyRefundFromPurchaseIdRequest().decode(payload);
+      return await applyRefundFromPurchaseId(ws, req.purchaseId);
+    }
     case "acceptBankIntegratedWithdrawal": {
       const req =
         codecForAcceptBankIntegratedWithdrawalRequest().decode(payload);
diff --git a/packages/taler-wallet-webextension/src/components/Part.tsx 
b/packages/taler-wallet-webextension/src/components/Part.tsx
index 58165a34..06e2985c 100644
--- a/packages/taler-wallet-webextension/src/components/Part.tsx
+++ b/packages/taler-wallet-webextension/src/components/Part.tsx
@@ -92,6 +92,7 @@ const CollasibleBox = styled.div`
   }
 `;
 import arrowDown from "../svg/chevron-down.svg";
+import { useTranslationContext } from "../context/translation.js";
 
 export function PartCollapsible({ text, title, big, showSign }: Props): VNode {
   const Text = big ? ExtraLargeText : LargeText;
@@ -137,27 +138,37 @@ interface PropsPayto {
 }
 export function PartPayto({ payto, kind, big }: PropsPayto): VNode {
   const Text = big ? ExtraLargeText : LargeText;
-  let text: string | undefined = undefined;
+  let text: VNode | undefined = undefined;
   let title = "";
+  const { i18n } = useTranslationContext();
   if (payto.isKnown) {
     if (payto.targetType === "x-taler-bank") {
-      text = payto.account;
-      title = "Bank account";
+      text = <Fragment>{payto.account}</Fragment>;
+      title = i18n.str`Bank account`;
     } else if (payto.targetType === "bitcoin") {
-      text = payto.targetPath;
-      title = "Bitcoin addr";
+      text =
+        payto.segwitAddrs && payto.segwitAddrs.length > 0 ? (
+          <ul>
+            <li>{payto.targetPath}</li>
+            <li>{payto.segwitAddrs[0]}</li>
+            <li>{payto.segwitAddrs[1]}</li>
+          </ul>
+        ) : (
+          <Fragment>{payto.targetPath}</Fragment>
+        );
+      title = i18n.str`Bitcoin address`;
     } else if (payto.targetType === "iban") {
-      text = payto.targetPath;
-      title = "IBAN";
+      text = <Fragment>{payto.targetPath}</Fragment>;
+      title = i18n.str`IBAN`;
     }
   }
   if (!text) {
-    text = stringifyPaytoUri(payto);
+    text = <Fragment>{stringifyPaytoUri(payto)}</Fragment>;
     title = "Payto URI";
   }
   return (
     <div style={{ margin: "1em" }}>
-      <SmallLightText style={{ margin: ".5em" }}>{title}</SmallLightText>
+      <SmallBoldText>{title}</SmallBoldText>
       <Text
         style={{
           color:
diff --git 
a/packages/taler-wallet-webextension/src/components/TransactionItem.tsx 
b/packages/taler-wallet-webextension/src/components/TransactionItem.tsx
index 985ddf55..bfffa326 100644
--- a/packages/taler-wallet-webextension/src/components/TransactionItem.tsx
+++ b/packages/taler-wallet-webextension/src/components/TransactionItem.tsx
@@ -207,7 +207,7 @@ function TransactionAmount(props: TransactionAmountProps): 
VNode {
     >
       <ExtraLargeText>
         {sign}
-        {Amounts.stringifyValue(props.amount)}
+        {Amounts.stringifyValue(props.amount, 2)}
       </ExtraLargeText>
       {props.pending && (
         <div>
diff --git a/packages/taler-wallet-webextension/src/wallet/History.stories.tsx 
b/packages/taler-wallet-webextension/src/wallet/History.stories.tsx
index 3080a866..004327c9 100644
--- a/packages/taler-wallet-webextension/src/wallet/History.stories.tsx
+++ b/packages/taler-wallet-webextension/src/wallet/History.stories.tsx
@@ -78,6 +78,7 @@ const exampleData = {
       summary: "the summary",
       fulfillmentMessage: "",
     },
+    refunds: [],
     refundPending: undefined,
     totalRefundEffective: "USD:0",
     totalRefundRaw: "USD:0",
diff --git a/packages/taler-wallet-webextension/src/wallet/History.tsx 
b/packages/taler-wallet-webextension/src/wallet/History.tsx
index 4a435d0c..59f24552 100644
--- a/packages/taler-wallet-webextension/src/wallet/History.tsx
+++ b/packages/taler-wallet-webextension/src/wallet/History.tsx
@@ -193,7 +193,7 @@ export function HistoryView({
                   margin: 8,
                 }}
               >
-                {Amounts.stringifyValue(currencyAmount)}
+                {Amounts.stringifyValue(currencyAmount, 2)}
               </CenteredBoldText>
             )}
           </div>
diff --git 
a/packages/taler-wallet-webextension/src/wallet/ReserveCreated.stories.tsx 
b/packages/taler-wallet-webextension/src/wallet/ReserveCreated.stories.tsx
index 587e24e9..895c301c 100644
--- a/packages/taler-wallet-webextension/src/wallet/ReserveCreated.stories.tsx
+++ b/packages/taler-wallet-webextension/src/wallet/ReserveCreated.stories.tsx
@@ -45,7 +45,7 @@ export const TalerBank = createExample(TestedComponent, {
 export const IBAN = createExample(TestedComponent, {
   reservePub: "A05AJGMFNSK4Q62NXR2FKNDB1J4EXTYQTE7VA4M9GZQ4TR06YBNG",
   paytoURI: parsePaytoUri(
-    
"payto://iban/ASDQWEASDZXCASDQWE?amount=COL%3A1&message=Taler+Withdrawal+A05AJGMFNSK4Q62NXR2FKNDB1J4EXTYQTE7VA4M9GZQ4TR06YBNG",
+    
"payto://iban/ES8877998399652238?amount=COL%3A1&message=Taler+Withdrawal+A05AJGMFNSK4Q62NXR2FKNDB1J4EXTYQTE7VA4M9GZQ4TR06YBNG",
   ),
   amount: {
     currency: "USD",
diff --git 
a/packages/taler-wallet-webextension/src/wallet/Transaction.stories.tsx 
b/packages/taler-wallet-webextension/src/wallet/Transaction.stories.tsx
index 493cdd1d..83848d00 100644
--- a/packages/taler-wallet-webextension/src/wallet/Transaction.stories.tsx
+++ b/packages/taler-wallet-webextension/src/wallet/Transaction.stories.tsx
@@ -93,6 +93,7 @@ const exampleData = {
       //   address_lines: [""],
       // },
     },
+    refunds: [],
     refundPending: undefined,
     totalRefundEffective: "KUDOS:0",
     totalRefundRaw: "KUDOS:0",
@@ -199,7 +200,7 @@ export const WithdrawPendingManual = 
createExample(TestedComponent, () => ({
     ...exampleData.withdraw,
     withdrawalDetails: {
       type: WithdrawalType.ManualTransfer,
-      exchangePaytoUris: ["payto://iban/asdasdasd"],
+      exchangePaytoUris: ["payto://iban/ES8877998399652238"],
       reservePub: "A05AJGMFNSK4Q62NXR2FKNDB1J4EXTYQTE7VA4M9GZQ4TR06YBNG",
     } as WithdrawalDetails,
     pending: true,
@@ -254,6 +255,14 @@ export const PaymentWithRefund = 
createExample(TestedComponent, {
     amountRaw: "KUDOS:12",
     totalRefundEffective: "KUDOS:1",
     totalRefundRaw: "KUDOS:1",
+    refunds: [
+      {
+        transactionId: "1123123",
+        amountRaw: "KUDOS:1",
+        amountEffective: "KUDOS:1",
+        timestamp: TalerProtocolTimestamp.fromSeconds(1546546544),
+      },
+    ],
   },
 });
 
@@ -410,6 +419,25 @@ export const PaymentWithLongSummary = 
createExample(TestedComponent, {
 export const Deposit = createExample(TestedComponent, {
   transaction: exampleData.deposit,
 });
+export const DepositTalerBank = createExample(TestedComponent, {
+  transaction: {
+    ...exampleData.deposit,
+    targetPaytoUri: "payto://x-taler-bank/bank.demo.taler.net/Exchange",
+  },
+});
+export const DepositBitcoin = createExample(TestedComponent, {
+  transaction: {
+    ...exampleData.deposit,
+    targetPaytoUri:
+      
"payto://bitcoin/bcrt1q6ps8qs6v8tkqrnru4xqqqa6rfwcx5ufpdfqht4?amount=BTC:0.1&subject=0ZSX8SH0M30KHX8K3Y1DAMVGDQV82XEF9DG1HC4QMQ3QWYT4AF00",
+  },
+});
+export const DepositIBAN = createExample(TestedComponent, {
+  transaction: {
+    ...exampleData.deposit,
+    targetPaytoUri: "payto://iban/ES8877998399652238",
+  },
+});
 
 export const DepositError = createExample(TestedComponent, {
   transaction: {
diff --git a/packages/taler-wallet-webextension/src/wallet/Transaction.tsx 
b/packages/taler-wallet-webextension/src/wallet/Transaction.tsx
index 9ccb353a..8165953a 100644
--- a/packages/taler-wallet-webextension/src/wallet/Transaction.tsx
+++ b/packages/taler-wallet-webextension/src/wallet/Transaction.tsx
@@ -22,6 +22,8 @@ import {
   NotificationType,
   parsePaytoUri,
   parsePayUri,
+  PaytoUri,
+  stringifyPaytoUri,
   TalerProtocolTimestamp,
   Transaction,
   TransactionDeposit,
@@ -50,6 +52,7 @@ import {
   ButtonDestructive,
   ButtonPrimary,
   CenteredDialog,
+  HistoryRow,
   InfoBox,
   ListOfProducts,
   Overlay,
@@ -83,7 +86,7 @@ async function getTransaction(tid: string): 
Promise<Transaction> {
 export function TransactionPage({ tid, goToWalletHistory }: Props): VNode {
   const { i18n } = useTranslationContext();
 
-  const state = useAsyncAsHook(() => getTransaction(tid));
+  const state = useAsyncAsHook(() => getTransaction(tid), [tid]);
 
   useEffect(() => {
     wxApi.onUpdateNotification([NotificationType.WithdrawGroupFinished], () => 
{
@@ -119,6 +122,7 @@ export function TransactionPage({ tid, goToWalletHistory }: 
Props): VNode {
       onRetry={() =>
         wxApi.retryTransaction(tid).then(() => goToWalletHistory(currency))
       }
+      onRefund={(id) => wxApi.applyRefundFromPurchaseId(id)}
       onBack={() => goToWalletHistory(currency)}
     />
   );
@@ -128,6 +132,7 @@ export interface WalletTransactionProps {
   transaction: Transaction;
   onDelete: () => void;
   onRetry: () => void;
+  onRefund: (id: string) => void;
   onBack: () => void;
 }
 
@@ -143,7 +148,7 @@ export function TransactionView({
   transaction,
   onDelete,
   onRetry,
-  onBack,
+  onRefund,
 }: WalletTransactionProps): VNode {
   const [confirmBeforeForget, setConfirmBeforeForget] = useState(false);
 
@@ -334,6 +339,40 @@ export function TransactionView({
           )}
         </Header>
         <br />
+        {transaction.refunds.length > 0 ? (
+          <Part
+            title={<i18n.Translate>Refunds</i18n.Translate>}
+            text={
+              <table>
+                {transaction.refunds.map((r, i) => {
+                  return (
+                    <tr key={i}>
+                      <td>
+                        {<Amount value={r.amountEffective} />}{" "}
+                        <a
+                          href={Pages.balance_transaction.replace(
+                            ":tid",
+                            r.transactionId,
+                          )}
+                        >
+                          was refunded
+                        </a>{" "}
+                        on{" "}
+                        {
+                          <Time
+                            timestamp={AbsoluteTime.fromTimestamp(r.timestamp)}
+                            format="dd MMMM yyyy"
+                          />
+                        }
+                      </td>
+                    </tr>
+                  );
+                })}
+              </table>
+            }
+            kind="neutral"
+          />
+        ) : undefined}
         {pendingRefund !== undefined && Amounts.isNonZero(pendingRefund) && (
           <InfoBox>
             <i18n.Translate>
@@ -348,7 +387,7 @@ export function TransactionView({
             <div>
               <div />
               <div>
-                <ButtonPrimary>
+                <ButtonPrimary onClick={() => 
onRefund(transaction.proposalId)}>
                   <i18n.Translate>Accept</i18n.Translate>
                 </ButtonPrimary>
               </div>
@@ -385,9 +424,9 @@ export function TransactionView({
           total={total}
           kind="negative"
         >
-          {transaction.targetPaytoUri}
+          {!payto ? transaction.targetPaytoUri : <NicePayto payto={payto} />}
         </Header>
-        {payto && <PartPayto big payto={payto} kind="neutral" />}
+        {payto && <PartPayto payto={payto} kind="neutral" />}
         <Part
           title={<i18n.Translate>Details</i18n.Translate>}
           text={<DepositDetails transaction={transaction} />}
@@ -669,7 +708,7 @@ function PurchaseDetails({
         <tr>
           <td>Refunded</td>
           <td>
-            <Amount value={transaction.totalRefundEffective} />
+            <Amount value={transaction.totalRefundRaw} />
           </td>
         </tr>
       )}
@@ -988,3 +1027,30 @@ function Header({
     </div>
   );
 }
+
+function NicePayto({ payto }: { payto: PaytoUri }): VNode {
+  if (payto.isKnown) {
+    switch (payto.targetType) {
+      case "bitcoin": {
+        return <div>{payto.targetPath.substring(0, 20)}...</div>;
+      }
+      case "x-taler-bank": {
+        const url = new URL("/", `https://${payto.host}`);
+        return (
+          <Fragment>
+            <div>{payto.account}</div>
+            <SmallLightText>
+              <a href={url.href} target="_bank" rel="noreferrer">
+                {url.toString()}
+              </a>
+            </SmallLightText>
+          </Fragment>
+        );
+      }
+      case "iban": {
+        return <div>{payto.targetPath.substring(0, 20)}</div>;
+      }
+    }
+  }
+  return <Fragment>{stringifyPaytoUri(payto)}</Fragment>;
+}
diff --git a/packages/taler-wallet-webextension/src/wxApi.ts 
b/packages/taler-wallet-webextension/src/wxApi.ts
index dd4eb2cf..63840017 100644
--- a/packages/taler-wallet-webextension/src/wxApi.ts
+++ b/packages/taler-wallet-webextension/src/wxApi.ts
@@ -311,6 +311,15 @@ export function applyRefund(
   return callBackend("applyRefund", { talerRefundUri });
 }
 
+/**
+ * Do refund for purchase.
+ */
+export function applyRefundFromPurchaseId(
+  purchaseId: string,
+): Promise<ApplyRefundResponse> {
+  return callBackend("applyRefundFromPurchaseId", { purchaseId });
+}
+
 /**
  * Get details about a pay operation.
  */

-- 
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]