738 lines
26 KiB
TypeScript
738 lines
26 KiB
TypeScript
import { action, observable, runInAction } from 'mobx';
|
|
import ReactNativeBlobUtil from 'react-native-blob-util';
|
|
import BigNumber from 'bignumber.js';
|
|
import { v4 as uuidv4 } from 'uuid';
|
|
|
|
import FiatStore from './FiatStore';
|
|
import SettingsStore, { PosEnabled } from './SettingsStore';
|
|
import UnitsStore from './UnitsStore';
|
|
|
|
import Order from '../models/Order';
|
|
|
|
import { SATS_PER_BTC } from '../utils/UnitsUtils';
|
|
import { calculateTaxSats } from '../utils/PosUtils';
|
|
import BackendUtils from '../utils/BackendUtils';
|
|
import { localeString } from '../utils/LocaleUtils';
|
|
|
|
import Storage from '../storage';
|
|
|
|
export interface orderPaymentInfo {
|
|
orderId: string;
|
|
orderTotal: string;
|
|
orderTip: string;
|
|
exchangeRate: string;
|
|
rate: number;
|
|
type: string; // ln OR onchain
|
|
tx: string; // txid OR payment request
|
|
preimage?: string;
|
|
}
|
|
|
|
export interface orderInvoiceInfo {
|
|
orderId: string;
|
|
payment_request: string;
|
|
rHash: string;
|
|
exchangeRate: string;
|
|
amount: string;
|
|
tip: string;
|
|
createdAt: number;
|
|
expirySeconds: string;
|
|
}
|
|
|
|
export const LEGACY_POS_HIDDEN_KEY = 'pos-hidden';
|
|
export const LEGACY_POS_STANDALONE_KEY = 'pos-standalone';
|
|
|
|
export const POS_HIDDEN_KEY = 'zeus-pos-hidden';
|
|
export const POS_STANDALONE_KEY = 'zeus-pos-standalone';
|
|
|
|
export default class PosStore {
|
|
@observable public currentOrder: Order | null = null;
|
|
@observable public openOrders: Array<Order> = [];
|
|
@observable public paidOrders: Array<Order> = [];
|
|
@observable public filteredOpenOrders: Array<Order> = [];
|
|
@observable public filteredPaidOrders: Array<Order> = [];
|
|
// recon
|
|
@observable public completedOrders: Array<Order> = [];
|
|
@observable public reconTotal: string = '0.00';
|
|
@observable public reconTax: string = '0.00';
|
|
@observable public reconTips: string = '0.00';
|
|
@observable public reconExport: string = '';
|
|
//
|
|
@observable public loading = false;
|
|
@observable public error = false;
|
|
|
|
settingsStore: SettingsStore;
|
|
fiatStore: FiatStore;
|
|
unitsStore: UnitsStore;
|
|
|
|
constructor(
|
|
settingsStore: SettingsStore,
|
|
fiatStore: FiatStore,
|
|
unitsStore: UnitsStore
|
|
) {
|
|
this.settingsStore = settingsStore;
|
|
this.fiatStore = fiatStore;
|
|
this.unitsStore = unitsStore;
|
|
}
|
|
|
|
private _enrichAndFilterOrders = async (orders: Order[]) => {
|
|
// fetch hidden orders - orders customers couldn't pay
|
|
const hiddenOrdersItem = await Storage.getItem(POS_HIDDEN_KEY);
|
|
const hiddenOrders = JSON.parse(hiddenOrdersItem || '[]');
|
|
|
|
const enrichedOrders = await Promise.all(
|
|
orders.map(async (order: any) => {
|
|
const payment = await Storage.getItem(`pos-${order.id}`);
|
|
if (hiddenOrders.includes(order.id)) {
|
|
order.hidden = true;
|
|
}
|
|
if (payment) {
|
|
order.payment = JSON.parse(payment);
|
|
}
|
|
return order;
|
|
})
|
|
);
|
|
|
|
const openOrders = enrichedOrders.filter(
|
|
(order: any) => !order.payment && !order.hidden
|
|
);
|
|
const paidOrders = enrichedOrders.filter((order: any) => order.payment);
|
|
|
|
runInAction(() => {
|
|
this.openOrders = openOrders;
|
|
this.filteredOpenOrders = openOrders;
|
|
this.paidOrders = paidOrders;
|
|
this.filteredPaidOrders = paidOrders;
|
|
this.loading = false;
|
|
});
|
|
};
|
|
|
|
@action
|
|
public processCheckout = async (
|
|
navigation: any,
|
|
isQuickPay: boolean = false
|
|
) => {
|
|
const currentOrder = this.currentOrder;
|
|
if (!currentOrder) return;
|
|
|
|
await this.saveStandaloneOrder(currentOrder);
|
|
|
|
if (!isQuickPay) {
|
|
navigation.navigate('Order', { order: currentOrder });
|
|
return;
|
|
}
|
|
|
|
const { settings } = this.settingsStore;
|
|
const { fiatRates, getRate } = this.fiatStore;
|
|
const { units } = this.unitsStore;
|
|
|
|
const { pos, fiat } = settings;
|
|
const merchantName = pos?.merchantName;
|
|
const taxPercentage = pos?.taxPercentage;
|
|
const lineItems = currentOrder.line_items;
|
|
|
|
const memo = merchantName
|
|
? `${merchantName} ${localeString(
|
|
'views.Settings.POS.poweredByZEUS'
|
|
)} - ${localeString('general.order')} ${currentOrder?.id}`
|
|
: `${localeString('views.Settings.POS')} - ${localeString(
|
|
'general.order'
|
|
)} ${currentOrder?.id}`;
|
|
|
|
const fiatEntry =
|
|
fiat && fiatRates
|
|
? fiatRates.filter((entry: any) => entry.code === fiat)[0]
|
|
: null;
|
|
const rate = fiat && fiatRates && fiatEntry ? fiatEntry.rate : 0;
|
|
|
|
const subTotalSats =
|
|
(currentOrder?.total_money?.sats ?? 0) > 0
|
|
? currentOrder.total_money.sats
|
|
: rate > 0
|
|
? new BigNumber(currentOrder?.total_money?.amount)
|
|
.div(100)
|
|
.div(rate)
|
|
.multipliedBy(SATS_PER_BTC)
|
|
.toFixed(0)
|
|
: '0';
|
|
|
|
const taxSats = Number(
|
|
calculateTaxSats(lineItems, subTotalSats, rate, taxPercentage)
|
|
);
|
|
|
|
const totalSats = new BigNumber(subTotalSats || 0)
|
|
.plus(taxSats)
|
|
.toFixed(0);
|
|
|
|
const totalFiat = new BigNumber(totalSats ?? 0)
|
|
.multipliedBy(rate)
|
|
.dividedBy(SATS_PER_BTC)
|
|
.toFixed(2);
|
|
|
|
const destination =
|
|
settings?.ecash?.enableCashu && BackendUtils.supportsCashuWallet()
|
|
? 'ReceiveEcash'
|
|
: 'Receive';
|
|
|
|
navigation.navigate(destination, {
|
|
amount:
|
|
units === 'sats'
|
|
? totalSats
|
|
: units === 'BTC'
|
|
? new BigNumber(totalSats || 0).div(SATS_PER_BTC).toFixed(8)
|
|
: totalFiat,
|
|
autoGenerate: true,
|
|
memo,
|
|
order: currentOrder,
|
|
orderId: currentOrder.id,
|
|
orderTip: 0,
|
|
orderTotal: totalSats,
|
|
exchangeRate: getRate(),
|
|
rate
|
|
});
|
|
};
|
|
|
|
@action
|
|
public hideOrder = async (orderId: string) => {
|
|
const hiddenOrdersItem = await Storage.getItem(POS_HIDDEN_KEY);
|
|
const hiddenOrders = JSON.parse(hiddenOrdersItem || '[]');
|
|
hiddenOrders.push(orderId);
|
|
await Storage.setItem(POS_HIDDEN_KEY, hiddenOrders);
|
|
};
|
|
|
|
@action
|
|
public updateSearch = (value: string) => {
|
|
this.filteredOpenOrders = this.openOrders.filter(
|
|
(item: any) =>
|
|
item.getItemsList.includes(value) ||
|
|
item.getItemsList.toLowerCase().includes(value)
|
|
);
|
|
this.filteredPaidOrders = this.paidOrders.filter(
|
|
(item: any) =>
|
|
item.getItemsList.includes(value) ||
|
|
item.getItemsList.toLowerCase().includes(value)
|
|
);
|
|
};
|
|
|
|
public recordPayment = ({
|
|
orderId,
|
|
orderTotal,
|
|
orderTip,
|
|
exchangeRate,
|
|
rate,
|
|
type,
|
|
tx,
|
|
preimage
|
|
}: orderPaymentInfo) =>
|
|
Storage.setItem(`pos-${orderId}`, {
|
|
orderId,
|
|
orderTotal,
|
|
orderTip,
|
|
exchangeRate,
|
|
rate,
|
|
type,
|
|
tx,
|
|
preimage
|
|
});
|
|
|
|
public recordInvoice = ({
|
|
orderId,
|
|
payment_request,
|
|
rHash,
|
|
exchangeRate,
|
|
amount,
|
|
tip,
|
|
createdAt,
|
|
expirySeconds
|
|
}: orderInvoiceInfo) => {
|
|
Storage.setItem(`pos-invoice-${orderId}`, {
|
|
orderId,
|
|
payment_request,
|
|
rHash,
|
|
exchangeRate,
|
|
amount,
|
|
tip,
|
|
createdAt,
|
|
expirySeconds
|
|
});
|
|
};
|
|
|
|
public clearCurrentOrder = () => (this.currentOrder = null);
|
|
|
|
public createCurrentOrder = (currency: string) => {
|
|
this.currentOrder = new Order({
|
|
id: uuidv4(),
|
|
created_at: new Date(Date.now()).toISOString(),
|
|
updated_at: new Date(Date.now()).toISOString(),
|
|
line_items: [],
|
|
total_tax_money: { amount: 0, currency },
|
|
total_money: { amount: 0, currency }
|
|
});
|
|
};
|
|
|
|
private calcFiatAmountFromSats = (amount: string | number) => {
|
|
const { fiatRates } = this.fiatStore;
|
|
const { settings } = this.settingsStore;
|
|
const { fiat } = settings;
|
|
|
|
// replace , with . for unit separator
|
|
const value = amount || '0';
|
|
|
|
const fiatEntry =
|
|
fiat && fiatRates
|
|
? fiatRates.filter((entry: any) => entry.code === fiat)[0]
|
|
: null;
|
|
|
|
const rate = fiat && fiatRates && fiatEntry ? fiatEntry.rate : 0;
|
|
|
|
const fiatAmount: string | number = rate
|
|
? new BigNumber(value.toString().replace(/,/g, '.'))
|
|
.dividedBy(SATS_PER_BTC)
|
|
.multipliedBy(rate)
|
|
.multipliedBy(100)
|
|
.toNumber()
|
|
.toFixed(0)
|
|
: 0;
|
|
|
|
return fiatAmount;
|
|
};
|
|
|
|
private calcSatsAmountFromFiat = (amount: string | number) => {
|
|
const { fiatRates } = this.fiatStore;
|
|
const { settings } = this.settingsStore;
|
|
const { fiat } = settings;
|
|
|
|
// replace , with . for unit separator
|
|
const value = amount || '0';
|
|
|
|
const fiatEntry =
|
|
fiat && fiatRates
|
|
? fiatRates.filter((entry: any) => entry.code === fiat)[0]
|
|
: null;
|
|
|
|
const rate = fiat && fiatRates && fiatEntry ? fiatEntry.rate : 0;
|
|
|
|
const satsAmount: string | number = rate
|
|
? new BigNumber(value.toString().replace(/,/g, '.'))
|
|
.dividedBy(rate)
|
|
.multipliedBy(SATS_PER_BTC)
|
|
.toNumber()
|
|
.toFixed(0)
|
|
: 0;
|
|
|
|
return satsAmount;
|
|
};
|
|
|
|
@action
|
|
public recalculateCurrentOrder = () => {
|
|
if (this.currentOrder) {
|
|
let totalFiat = new BigNumber(0);
|
|
let totalSats = new BigNumber(0);
|
|
this.currentOrder.line_items.forEach((item) => {
|
|
if (item.base_price_money.sats! > 0) {
|
|
const addedAmount = new BigNumber(
|
|
item.base_price_money.sats || 0
|
|
).times(item.quantity);
|
|
totalSats = totalSats.plus(addedAmount);
|
|
totalFiat = totalFiat.plus(
|
|
this.calcFiatAmountFromSats(addedAmount.toNumber())
|
|
);
|
|
} else {
|
|
const addedAmount = new BigNumber(
|
|
item.base_price_money.amount || 0
|
|
).times(item.quantity);
|
|
totalFiat = totalFiat.plus(addedAmount.times(100));
|
|
totalSats = totalSats.plus(
|
|
this.calcSatsAmountFromFiat(addedAmount.toNumber())
|
|
);
|
|
}
|
|
});
|
|
|
|
this.currentOrder.total_money.amount = totalFiat.toNumber();
|
|
this.currentOrder.total_money.sats = totalSats.toNumber();
|
|
|
|
// calculate taxes using individual product rates when available
|
|
const { settings } = this.settingsStore;
|
|
const { taxPercentage } = settings.pos;
|
|
|
|
// Check if any line items have individual tax rates
|
|
const hasIndividualTaxRates = this.currentOrder.line_items.some(
|
|
(item) => item.taxPercentage && item.taxPercentage !== ''
|
|
);
|
|
|
|
if (
|
|
hasIndividualTaxRates ||
|
|
(taxPercentage && taxPercentage !== '0' && taxPercentage !== '')
|
|
) {
|
|
let totalTaxFiat = new BigNumber(0);
|
|
|
|
if (hasIndividualTaxRates) {
|
|
this.currentOrder.line_items.forEach((item) => {
|
|
const itemTaxRate =
|
|
item.taxPercentage && item.taxPercentage !== ''
|
|
? item.taxPercentage
|
|
: taxPercentage || '0';
|
|
|
|
let itemSubtotalFiat: BigNumber;
|
|
|
|
if (item.base_price_money.sats! > 0) {
|
|
const satsAmount = new BigNumber(
|
|
item.base_price_money.sats || 0
|
|
).times(item.quantity);
|
|
itemSubtotalFiat = new BigNumber(
|
|
this.calcFiatAmountFromSats(
|
|
satsAmount.toNumber()
|
|
)
|
|
).div(100);
|
|
} else {
|
|
itemSubtotalFiat = new BigNumber(
|
|
item.base_price_money.amount || 0
|
|
).times(item.quantity);
|
|
}
|
|
|
|
const itemTaxFiat = itemSubtotalFiat
|
|
.multipliedBy(new BigNumber(itemTaxRate))
|
|
.dividedBy(100);
|
|
|
|
totalTaxFiat = totalTaxFiat.plus(itemTaxFiat);
|
|
});
|
|
} else {
|
|
totalTaxFiat = totalFiat
|
|
.div(100)
|
|
.multipliedBy(Number(taxPercentage) || 0);
|
|
}
|
|
|
|
this.currentOrder.total_tax_money.amount =
|
|
totalTaxFiat.toNumber();
|
|
|
|
if (this.fiatStore.fiatRates) {
|
|
const fiatEntry = this.fiatStore.fiatRates.filter(
|
|
(entry: any) =>
|
|
entry.code === this.settingsStore.settings.fiat
|
|
)[0];
|
|
const { code } = fiatEntry;
|
|
this.currentOrder.total_tax_money.currency = code;
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
public saveStandaloneOrder = async (updateOrder: Order) => {
|
|
const order = this.openOrders.find((o) => o.id === updateOrder.id);
|
|
|
|
if (order) {
|
|
order.line_items = updateOrder.line_items;
|
|
order.updated_at = new Date(Date.now()).toISOString();
|
|
order.total_money = updateOrder.total_money;
|
|
} else {
|
|
this.openOrders.push(updateOrder);
|
|
}
|
|
|
|
await Storage.setItem(
|
|
POS_STANDALONE_KEY,
|
|
this.openOrders.concat(this.paidOrders)
|
|
);
|
|
|
|
this.clearCurrentOrder();
|
|
};
|
|
|
|
public getOrders = async () => {
|
|
switch (this.settingsStore.settings.pos.posEnabled) {
|
|
case PosEnabled.Square:
|
|
return this.getSquareOrders();
|
|
|
|
case PosEnabled.Standalone:
|
|
return this.getStandaloneOrders();
|
|
|
|
default:
|
|
this.resetOrders();
|
|
break;
|
|
}
|
|
};
|
|
|
|
@action
|
|
private getStandaloneOrders = async () => {
|
|
this.loading = true;
|
|
this.error = false;
|
|
|
|
const soOrders = await Storage.getItem(POS_STANDALONE_KEY);
|
|
|
|
const orders = JSON.parse(soOrders || '[]').map(
|
|
(order: any) => new Order(order)
|
|
);
|
|
|
|
await this._enrichAndFilterOrders(orders);
|
|
};
|
|
|
|
@action
|
|
private getSquareOrders = async () => {
|
|
const { squareAccessToken, squareLocationId, squareDevMode } =
|
|
this.settingsStore.settings.pos;
|
|
this.loading = true;
|
|
this.error = false;
|
|
const apiHost = squareDevMode
|
|
? 'https://connect.squareupsandbox.com'
|
|
: 'https://connect.squareup.com';
|
|
ReactNativeBlobUtil.fetch(
|
|
'POST',
|
|
`${apiHost}/v2/orders/search`,
|
|
{
|
|
Authorization: `Bearer ${squareAccessToken}`,
|
|
'Content-Type': 'application/json'
|
|
},
|
|
JSON.stringify({
|
|
location_ids: [squareLocationId]
|
|
})
|
|
)
|
|
.then(async (response: any) => {
|
|
const status = response.info().status;
|
|
if (status == 200) {
|
|
this.loading = false;
|
|
let orders = response
|
|
.json()
|
|
.orders.map((order: any) => new Order(order))
|
|
.filter((order: any) => {
|
|
return (
|
|
order.tenders &&
|
|
order.tenders[0] &&
|
|
order.tenders[0].note &&
|
|
(order.tenders[0].note
|
|
.toLowerCase()
|
|
.includes('zeus') ||
|
|
order.tenders[0].note
|
|
.toLowerCase()
|
|
.includes('zues') ||
|
|
order.tenders[0].note
|
|
.toLowerCase()
|
|
.includes('bitcoin') ||
|
|
order.tenders[0].note
|
|
.toLowerCase()
|
|
.includes('btc') ||
|
|
order.tenders[0].note
|
|
.toLowerCase()
|
|
.includes('bit coin'))
|
|
);
|
|
});
|
|
|
|
await this._enrichAndFilterOrders(orders);
|
|
} else {
|
|
runInAction(() => {
|
|
this.openOrders = [];
|
|
this.paidOrders = [];
|
|
this.loading = false;
|
|
this.error = true;
|
|
});
|
|
}
|
|
})
|
|
.catch((err) => {
|
|
console.error('POS get orders err', err);
|
|
runInAction(() => {
|
|
this.openOrders = [];
|
|
this.paidOrders = [];
|
|
this.loading = false;
|
|
this.error = true;
|
|
});
|
|
});
|
|
};
|
|
|
|
@action
|
|
public getOrdersHistorical = async (hours = 24) => {
|
|
const { squareAccessToken, squareLocationId, squareDevMode } =
|
|
this.settingsStore.settings.pos;
|
|
this.loading = true;
|
|
this.error = false;
|
|
const apiHost = squareDevMode
|
|
? 'https://connect.squareupsandbox.com'
|
|
: 'https://connect.squareup.com';
|
|
ReactNativeBlobUtil.fetch(
|
|
'POST',
|
|
`${apiHost}/v2/orders/search`,
|
|
{
|
|
Authorization: `Bearer ${squareAccessToken}`,
|
|
'Content-Type': 'application/json'
|
|
},
|
|
JSON.stringify({
|
|
limit: 10000,
|
|
location_ids: [squareLocationId],
|
|
query: {
|
|
filter: {
|
|
date_time_filter: {
|
|
created_at: {
|
|
start_at: new Date(
|
|
Date.now() - hours * 60 * 60 * 1000
|
|
).toISOString(),
|
|
end_at: new Date().toISOString()
|
|
}
|
|
},
|
|
state_filter: {
|
|
states: ['COMPLETED']
|
|
}
|
|
}
|
|
},
|
|
sort: {
|
|
sort_field: 'CREATED_AT',
|
|
sort_order: 'DESC'
|
|
}
|
|
})
|
|
)
|
|
.then(async (response: any) => {
|
|
const status = response.info().status;
|
|
if (status == 200) {
|
|
this.loading = false;
|
|
let orders = response
|
|
.json()
|
|
.orders.map((order: any) => new Order(order))
|
|
.filter((order: any) => {
|
|
return (
|
|
order.tenders &&
|
|
order.tenders[0] &&
|
|
order.tenders[0].note &&
|
|
(order.tenders[0].note
|
|
.toLowerCase()
|
|
.includes('zeus') ||
|
|
order.tenders[0].note
|
|
.toLowerCase()
|
|
.includes('zues') ||
|
|
order.tenders[0].note
|
|
.toLowerCase()
|
|
.includes('bitcoin') ||
|
|
order.tenders[0].note
|
|
.toLowerCase()
|
|
.includes('btc') ||
|
|
order.tenders[0].note
|
|
.toLowerCase()
|
|
.includes('bit coin'))
|
|
);
|
|
});
|
|
|
|
let total = 0;
|
|
let tax = 0;
|
|
let tips = 0;
|
|
let exportString =
|
|
'orderId, totalSats, tipSats, rateFull, rateNumerical, type, tx\n';
|
|
|
|
// fetch hidden orders - orders customers couldn't pay
|
|
const hiddenOrdersItem = await Storage.getItem(
|
|
POS_HIDDEN_KEY
|
|
);
|
|
const hiddenOrders = JSON.parse(hiddenOrdersItem || '[]');
|
|
|
|
const enrichedOrders = await Promise.all(
|
|
orders.map(async (order: any) => {
|
|
const payment = await Storage.getItem(
|
|
`pos-${order.id}`
|
|
);
|
|
let tip;
|
|
// mark order if hidden
|
|
if (hiddenOrders.includes(order.id)) {
|
|
order.hidden = true;
|
|
}
|
|
if (payment) {
|
|
order.payment = JSON.parse(payment);
|
|
const {
|
|
orderId,
|
|
orderTotal,
|
|
orderTip,
|
|
exchangeRate,
|
|
rate,
|
|
type,
|
|
tx
|
|
} = order.payment;
|
|
tip = new BigNumber(orderTip)
|
|
.multipliedBy(rate)
|
|
.dividedBy(SATS_PER_BTC)
|
|
.toFixed(2);
|
|
|
|
exportString += `${orderId}, ${orderTotal}, ${orderTip}, ${exchangeRate}, ${rate}, ${type}, ${tx}\n`;
|
|
}
|
|
|
|
// tally totals
|
|
total +=
|
|
Number(order.getTotalMoney) +
|
|
Number(order.getTaxMoney);
|
|
tax += Number(order.getTaxMoney);
|
|
tips += tip
|
|
? Number(tip)
|
|
: order.autoGratuity
|
|
? Number(order.autoGratuity)
|
|
: 0;
|
|
return order;
|
|
})
|
|
);
|
|
|
|
runInAction(() => {
|
|
this.completedOrders = enrichedOrders;
|
|
this.reconTotal = total.toFixed(2);
|
|
this.reconTax = tax.toFixed(2);
|
|
this.reconTips = tips.toFixed(2);
|
|
this.reconExport = exportString;
|
|
});
|
|
} else {
|
|
runInAction(() => {
|
|
this.completedOrders = [];
|
|
this.loading = false;
|
|
this.error = true;
|
|
});
|
|
}
|
|
})
|
|
.catch((err) => {
|
|
console.error('POS get historical orders err', err);
|
|
runInAction(() => {
|
|
this.completedOrders = [];
|
|
this.loading = false;
|
|
this.error = true;
|
|
});
|
|
});
|
|
};
|
|
|
|
@action
|
|
public getOrderPaymentById = async (
|
|
orderId: string
|
|
): Promise<Order | undefined> => {
|
|
const payment = await Storage.getItem(`pos-${orderId}`);
|
|
|
|
if (payment) {
|
|
return JSON.parse(payment);
|
|
}
|
|
};
|
|
|
|
public getOrderInvoiceById = async (
|
|
orderId: string
|
|
): Promise<orderInvoiceInfo | undefined> => {
|
|
const invoice = await Storage.getItem(`pos-invoice-${orderId}`);
|
|
if (invoice) {
|
|
return JSON.parse(invoice);
|
|
}
|
|
};
|
|
|
|
public clearOrderInvoice = (orderId: string) =>
|
|
Storage.removeItem(`pos-invoice-${orderId}`);
|
|
|
|
public isInvoiceValid = (invoiceInfo: orderInvoiceInfo): boolean => {
|
|
const now = Date.now() / 1000;
|
|
const expiryTime =
|
|
invoiceInfo.createdAt + parseInt(invoiceInfo.expirySeconds, 10);
|
|
return expiryTime > now + 60;
|
|
};
|
|
|
|
public canReuseInvoice = (
|
|
invoiceInfo: orderInvoiceInfo,
|
|
currentAmount: string,
|
|
currentTip: string,
|
|
currentExchangeRate: string
|
|
): boolean => {
|
|
return (
|
|
this.isInvoiceValid(invoiceInfo) &&
|
|
invoiceInfo.amount === currentAmount &&
|
|
invoiceInfo.tip === currentTip &&
|
|
invoiceInfo.exchangeRate === currentExchangeRate
|
|
);
|
|
};
|
|
|
|
@action
|
|
private resetOrders = () => {
|
|
this.openOrders = [];
|
|
this.paidOrders = [];
|
|
this.loading = false;
|
|
};
|
|
}
|