@zeniai/client-epic-state 5.2.80 → 5.2.82
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/esm/view/expenseAutomationView/helpers/transactionCategorizationLocalDataHelper.js +5 -1
- package/lib/esm/view/invoicing/editInvoicingSubscriptionDetailView/editInvoicingSubscriptionDetailViewPayload.js +50 -0
- package/lib/index.d.ts +1 -1
- package/lib/view/expenseAutomationView/helpers/transactionCategorizationLocalDataHelper.js +5 -1
- package/lib/view/invoicing/editInvoicingSubscriptionDetailView/editInvoicingSubscriptionDetailViewPayload.d.ts +10 -0
- package/lib/view/invoicing/editInvoicingSubscriptionDetailView/editInvoicingSubscriptionDetailViewPayload.js +50 -0
- package/lib/view/invoicing/editInvoicingSubscriptionDetailView/editInvoicingSubscriptionDetailViewState.d.ts +13 -0
- package/package.json +1 -1
package/lib/esm/view/expenseAutomationView/helpers/transactionCategorizationLocalDataHelper.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { isCustomerTransaction, } from '../../../entity/transaction/stateTypes/customerTransaction';
|
|
1
2
|
import { isVendorTransaction } from '../../../entity/transaction/stateTypes/vendorTransaction';
|
|
2
3
|
import { isEntityMatching, mergeTransactionAndEntityRecommendationsWithCOT, toLineEntity, } from '../../transactionDetail/transactionDetailLocalDataHelper';
|
|
3
4
|
import { isAccountUncategorized } from '../../transactionDetail/transactionDetailLocalDataHelper';
|
|
@@ -208,7 +209,10 @@ const buildLineItemById = (transaction, recommendations) => {
|
|
|
208
209
|
logo: accountLine.vendor.logo,
|
|
209
210
|
}
|
|
210
211
|
: undefined;
|
|
211
|
-
const customer = accountLine.customer
|
|
212
|
+
const customer = accountLine.customer ??
|
|
213
|
+
(isCustomerTransaction(transaction) === true
|
|
214
|
+
? transaction.customer
|
|
215
|
+
: undefined);
|
|
212
216
|
record.customer =
|
|
213
217
|
customer != null && Boolean(customer.id) && Boolean(customer.name)
|
|
214
218
|
? {
|
|
@@ -59,11 +59,59 @@ export const localDataToSaveInvoicingSubscriptionPayload = (localData, shippingA
|
|
|
59
59
|
};
|
|
60
60
|
};
|
|
61
61
|
const toEstimateDate = (value) => value != null && value !== '' ? date(value) : undefined;
|
|
62
|
+
const isItemLevelCoupon = (discount) => discount.entity_type === 'item_level_coupon';
|
|
63
|
+
const isCoupon = (discount) => discount.entity_type === 'document_level_coupon' ||
|
|
64
|
+
discount.entity_type === 'item_level_coupon';
|
|
65
|
+
/**
|
|
66
|
+
* Name the coupon behind a line's discount. Exact when the API links a coupon
|
|
67
|
+
* row to its line (`line_item_id`); otherwise only when a single item-level
|
|
68
|
+
* coupon applies, since then every discounted line got that one.
|
|
69
|
+
*/
|
|
70
|
+
const lineDiscountLabel = (lineItem, discounts) => {
|
|
71
|
+
if (lineItem.discount_amount <= 0) {
|
|
72
|
+
return undefined;
|
|
73
|
+
}
|
|
74
|
+
const itemCoupons = discounts.filter(isItemLevelCoupon);
|
|
75
|
+
const linked = lineItem.id != null
|
|
76
|
+
? itemCoupons.filter((coupon) => coupon.line_item_id === lineItem.id)
|
|
77
|
+
: [];
|
|
78
|
+
if (linked.length > 0) {
|
|
79
|
+
return [...new Set(linked.map((coupon) => coupon.description))].join(', ');
|
|
80
|
+
}
|
|
81
|
+
const names = [...new Set(itemCoupons.map((coupon) => coupon.description))];
|
|
82
|
+
return names.length === 1 ? names[0] : undefined;
|
|
83
|
+
};
|
|
84
|
+
/**
|
|
85
|
+
* One row per coupon. An item-level coupon comes back once per line it
|
|
86
|
+
* discounted, so its rows are summed; listing each would read as the same
|
|
87
|
+
* discount taken several times.
|
|
88
|
+
*/
|
|
89
|
+
const mergeCouponRows = (discounts) => {
|
|
90
|
+
const rowsByCoupon = new Map();
|
|
91
|
+
discounts.filter(isCoupon).forEach((coupon) => {
|
|
92
|
+
// The API sends `entity_id: ""` when it has none; key those by name so
|
|
93
|
+
// two unrelated coupons are not merged into one row.
|
|
94
|
+
const couponKey = coupon.entity_id != null && coupon.entity_id !== ''
|
|
95
|
+
? coupon.entity_id
|
|
96
|
+
: coupon.description;
|
|
97
|
+
const key = `${coupon.entity_type}:${couponKey}`;
|
|
98
|
+
const row = rowsByCoupon.get(key);
|
|
99
|
+
rowsByCoupon.set(key, {
|
|
100
|
+
amount: Math.round(((row?.amount ?? 0) + coupon.amount) * 100) / 100,
|
|
101
|
+
description: coupon.description,
|
|
102
|
+
});
|
|
103
|
+
});
|
|
104
|
+
return [...rowsByCoupon.values()];
|
|
105
|
+
};
|
|
62
106
|
const mapInvoiceEstimate = (payload, money) => payload == null
|
|
63
107
|
? undefined
|
|
64
108
|
: {
|
|
65
109
|
amountDue: money(payload.amount_due),
|
|
66
110
|
couponDiscountTotal: money(payload.coupon_discount_total),
|
|
111
|
+
coupons: mergeCouponRows(payload.discounts ?? []).map((coupon) => ({
|
|
112
|
+
amount: money(coupon.amount),
|
|
113
|
+
description: coupon.description,
|
|
114
|
+
})),
|
|
67
115
|
creditsApplied: money(payload.credits_applied),
|
|
68
116
|
dueDate: toEstimateDate(payload.due_date),
|
|
69
117
|
grossSubTotal: money(payload.gross_sub_total),
|
|
@@ -74,6 +122,8 @@ const mapInvoiceEstimate = (payload, money) => payload == null
|
|
|
74
122
|
dateTo: toEstimateDate(lineItem.date_to),
|
|
75
123
|
description: lineItem.description,
|
|
76
124
|
discountAmount: money(lineItem.discount_amount),
|
|
125
|
+
discountLabel: lineDiscountLabel(lineItem, payload.discounts ?? []),
|
|
126
|
+
grossAmount: money(lineItem.gross_amount ?? lineItem.amount),
|
|
77
127
|
quantity: lineItem.quantity,
|
|
78
128
|
taxAmount: lineItem.tax_amount != null
|
|
79
129
|
? money(lineItem.tax_amount)
|
package/lib/index.d.ts
CHANGED
|
@@ -1128,7 +1128,7 @@ export { getInvoicingCustomerFormView } from './view/invoicing/editInvoicingCust
|
|
|
1128
1128
|
export type { InvoicingCustomerFormView } from './view/invoicing/editInvoicingCustomerDetailView/editInvoicingCustomerDetailViewSelector';
|
|
1129
1129
|
export { clearInvoicingSubscriptionEstimate, fetchInvoicingSubscriptionEstimate, fetchInvoicingSubscriptionFormPage, initializeInvoicingSubscriptionAddress, resetEditInvoicingSubscriptionDetailView, submitInvoicingSubscriptionForm, updateInvoicingSubscriptionFormDraft, } from './view/invoicing/editInvoicingSubscriptionDetailView/editInvoicingSubscriptionDetailViewReducer';
|
|
1130
1130
|
export type { SubmitInvoicingSubscriptionFormPayload, UpdateInvoicingSubscriptionFormDraftPayload, } from './view/invoicing/editInvoicingSubscriptionDetailView/editInvoicingSubscriptionDetailViewReducer';
|
|
1131
|
-
export type { InvoicingSubscriptionEstimateLineItem, InvoicingSubscriptionFormLocalData, InvoicingSubscriptionInvoiceEstimate, } from './view/invoicing/editInvoicingSubscriptionDetailView/editInvoicingSubscriptionDetailViewState';
|
|
1131
|
+
export type { InvoicingSubscriptionEstimateCoupon, InvoicingSubscriptionEstimateLineItem, InvoicingSubscriptionFormLocalData, InvoicingSubscriptionInvoiceEstimate, } from './view/invoicing/editInvoicingSubscriptionDetailView/editInvoicingSubscriptionDetailViewState';
|
|
1132
1132
|
export { INVOICING_SUBSCRIPTION_SHIPPING_ADDRESS_TYPE, entityToInvoicingSubscriptionFormLocalData, initialInvoicingSubscriptionFormLocalData, invoicingSubscriptionTodayIso, toInvoicingSubscriptionQuantity, } from './view/invoicing/editInvoicingSubscriptionDetailView/invoicingSubscriptionFormConfig';
|
|
1133
1133
|
export { getEditInvoicingSubscriptionDetailViewState, getInvoicingSubscriptionFormView, } from './view/invoicing/editInvoicingSubscriptionDetailView/editInvoicingSubscriptionDetailViewSelector';
|
|
1134
1134
|
export type { EditInvoicingSubscriptionDetailView, InvoicingSubscriptionEstimateKind, InvoicingSubscriptionEstimateView, InvoicingSubscriptionFormView, InvoicingSubscriptionOption, } from './view/invoicing/editInvoicingSubscriptionDetailView/editInvoicingSubscriptionDetailViewSelector';
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.hasTransactionLocalDataChanges = exports.isAnyItemWithUncategorizedExpenseAccount = exports.getSnackbarMessageForTransactionReview = exports.mergeTabSpecificLineItems = exports.getLineItemsByTransactionIdsFromLocalData = exports.getLineItemsByTransactionsIdsFromResponse = exports.checkIfAllLineItemsAreCategoryClassFilled = exports.setEntityRecommendationForLineIdInLocalData = exports.toSetAllLineItemsToCategoryClass = exports.toTransactionDetailLocalData = exports.shouldAutoSelectAndAdd = exports.MAX_SELECTION_LIMIT = exports.filterAutoTabLineItems = exports.removeTransactionFromTabView = exports.getPendingReviewLineIdsFromTransaction = void 0;
|
|
4
|
+
const customerTransaction_1 = require("../../../entity/transaction/stateTypes/customerTransaction");
|
|
4
5
|
const vendorTransaction_1 = require("../../../entity/transaction/stateTypes/vendorTransaction");
|
|
5
6
|
const transactionDetailLocalDataHelper_1 = require("../../transactionDetail/transactionDetailLocalDataHelper");
|
|
6
7
|
const transactionDetailLocalDataHelper_2 = require("../../transactionDetail/transactionDetailLocalDataHelper");
|
|
@@ -216,7 +217,10 @@ const buildLineItemById = (transaction, recommendations) => {
|
|
|
216
217
|
logo: accountLine.vendor.logo,
|
|
217
218
|
}
|
|
218
219
|
: undefined;
|
|
219
|
-
const customer = accountLine.customer
|
|
220
|
+
const customer = accountLine.customer ??
|
|
221
|
+
((0, customerTransaction_1.isCustomerTransaction)(transaction) === true
|
|
222
|
+
? transaction.customer
|
|
223
|
+
: undefined);
|
|
220
224
|
record.customer =
|
|
221
225
|
customer != null && Boolean(customer.id) && Boolean(customer.name)
|
|
222
226
|
? {
|
|
@@ -82,8 +82,17 @@ interface InvoicingSubscriptionEstimateLineItemPayload {
|
|
|
82
82
|
unit_amount: number;
|
|
83
83
|
date_from?: string;
|
|
84
84
|
date_to?: string;
|
|
85
|
+
gross_amount?: number;
|
|
86
|
+
id?: string;
|
|
85
87
|
tax_amount?: number | null;
|
|
86
88
|
}
|
|
89
|
+
interface InvoicingSubscriptionEstimateDiscountPayload {
|
|
90
|
+
amount: number;
|
|
91
|
+
description: string;
|
|
92
|
+
entity_type: string;
|
|
93
|
+
entity_id?: string;
|
|
94
|
+
line_item_id?: string | null;
|
|
95
|
+
}
|
|
87
96
|
interface InvoicingSubscriptionInvoiceEstimatePayload {
|
|
88
97
|
amount_due: number;
|
|
89
98
|
coupon_discount_total: number;
|
|
@@ -94,6 +103,7 @@ interface InvoicingSubscriptionInvoiceEstimatePayload {
|
|
|
94
103
|
sub_total: number;
|
|
95
104
|
tax: number | null;
|
|
96
105
|
total: number;
|
|
106
|
+
discounts?: InvoicingSubscriptionEstimateDiscountPayload[];
|
|
97
107
|
due_date?: string;
|
|
98
108
|
invoice_date?: string;
|
|
99
109
|
}
|
|
@@ -63,11 +63,59 @@ const localDataToSaveInvoicingSubscriptionPayload = (localData, shippingAddress)
|
|
|
63
63
|
};
|
|
64
64
|
exports.localDataToSaveInvoicingSubscriptionPayload = localDataToSaveInvoicingSubscriptionPayload;
|
|
65
65
|
const toEstimateDate = (value) => value != null && value !== '' ? (0, zeniDayJS_1.date)(value) : undefined;
|
|
66
|
+
const isItemLevelCoupon = (discount) => discount.entity_type === 'item_level_coupon';
|
|
67
|
+
const isCoupon = (discount) => discount.entity_type === 'document_level_coupon' ||
|
|
68
|
+
discount.entity_type === 'item_level_coupon';
|
|
69
|
+
/**
|
|
70
|
+
* Name the coupon behind a line's discount. Exact when the API links a coupon
|
|
71
|
+
* row to its line (`line_item_id`); otherwise only when a single item-level
|
|
72
|
+
* coupon applies, since then every discounted line got that one.
|
|
73
|
+
*/
|
|
74
|
+
const lineDiscountLabel = (lineItem, discounts) => {
|
|
75
|
+
if (lineItem.discount_amount <= 0) {
|
|
76
|
+
return undefined;
|
|
77
|
+
}
|
|
78
|
+
const itemCoupons = discounts.filter(isItemLevelCoupon);
|
|
79
|
+
const linked = lineItem.id != null
|
|
80
|
+
? itemCoupons.filter((coupon) => coupon.line_item_id === lineItem.id)
|
|
81
|
+
: [];
|
|
82
|
+
if (linked.length > 0) {
|
|
83
|
+
return [...new Set(linked.map((coupon) => coupon.description))].join(', ');
|
|
84
|
+
}
|
|
85
|
+
const names = [...new Set(itemCoupons.map((coupon) => coupon.description))];
|
|
86
|
+
return names.length === 1 ? names[0] : undefined;
|
|
87
|
+
};
|
|
88
|
+
/**
|
|
89
|
+
* One row per coupon. An item-level coupon comes back once per line it
|
|
90
|
+
* discounted, so its rows are summed; listing each would read as the same
|
|
91
|
+
* discount taken several times.
|
|
92
|
+
*/
|
|
93
|
+
const mergeCouponRows = (discounts) => {
|
|
94
|
+
const rowsByCoupon = new Map();
|
|
95
|
+
discounts.filter(isCoupon).forEach((coupon) => {
|
|
96
|
+
// The API sends `entity_id: ""` when it has none; key those by name so
|
|
97
|
+
// two unrelated coupons are not merged into one row.
|
|
98
|
+
const couponKey = coupon.entity_id != null && coupon.entity_id !== ''
|
|
99
|
+
? coupon.entity_id
|
|
100
|
+
: coupon.description;
|
|
101
|
+
const key = `${coupon.entity_type}:${couponKey}`;
|
|
102
|
+
const row = rowsByCoupon.get(key);
|
|
103
|
+
rowsByCoupon.set(key, {
|
|
104
|
+
amount: Math.round(((row?.amount ?? 0) + coupon.amount) * 100) / 100,
|
|
105
|
+
description: coupon.description,
|
|
106
|
+
});
|
|
107
|
+
});
|
|
108
|
+
return [...rowsByCoupon.values()];
|
|
109
|
+
};
|
|
66
110
|
const mapInvoiceEstimate = (payload, money) => payload == null
|
|
67
111
|
? undefined
|
|
68
112
|
: {
|
|
69
113
|
amountDue: money(payload.amount_due),
|
|
70
114
|
couponDiscountTotal: money(payload.coupon_discount_total),
|
|
115
|
+
coupons: mergeCouponRows(payload.discounts ?? []).map((coupon) => ({
|
|
116
|
+
amount: money(coupon.amount),
|
|
117
|
+
description: coupon.description,
|
|
118
|
+
})),
|
|
71
119
|
creditsApplied: money(payload.credits_applied),
|
|
72
120
|
dueDate: toEstimateDate(payload.due_date),
|
|
73
121
|
grossSubTotal: money(payload.gross_sub_total),
|
|
@@ -78,6 +126,8 @@ const mapInvoiceEstimate = (payload, money) => payload == null
|
|
|
78
126
|
dateTo: toEstimateDate(lineItem.date_to),
|
|
79
127
|
description: lineItem.description,
|
|
80
128
|
discountAmount: money(lineItem.discount_amount),
|
|
129
|
+
discountLabel: lineDiscountLabel(lineItem, payload.discounts ?? []),
|
|
130
|
+
grossAmount: money(lineItem.gross_amount ?? lineItem.amount),
|
|
81
131
|
quantity: lineItem.quantity,
|
|
82
132
|
taxAmount: lineItem.tax_amount != null
|
|
83
133
|
? money(lineItem.tax_amount)
|
|
@@ -41,19 +41,32 @@ export interface InvoicingSubscriptionFormLocalData {
|
|
|
41
41
|
setupFee?: Amount;
|
|
42
42
|
}
|
|
43
43
|
export interface InvoicingSubscriptionEstimateLineItem {
|
|
44
|
+
/** After the line's own (item-level) coupons. */
|
|
44
45
|
amount: Amount;
|
|
45
46
|
description: string;
|
|
47
|
+
/** Item-level coupons on this line; invoice-level coupons are not spread here. */
|
|
46
48
|
discountAmount: Amount;
|
|
49
|
+
/** Before any coupon, so the lines add up to `grossSubTotal`. */
|
|
50
|
+
grossAmount: Amount;
|
|
47
51
|
quantity: number;
|
|
48
52
|
unitAmount: Amount;
|
|
49
53
|
dateFrom?: ZeniDate;
|
|
50
54
|
dateTo?: ZeniDate;
|
|
55
|
+
/** The coupon behind `discountAmount`, when it can be told; see the mapper. */
|
|
56
|
+
discountLabel?: string;
|
|
51
57
|
taxAmount?: Amount;
|
|
52
58
|
}
|
|
59
|
+
/** A coupon the estimate applies, named, for the totals. */
|
|
60
|
+
export interface InvoicingSubscriptionEstimateCoupon {
|
|
61
|
+
amount: Amount;
|
|
62
|
+
description: string;
|
|
63
|
+
}
|
|
53
64
|
/** An invoice the save would raise now, or the next one it would raise later. */
|
|
54
65
|
export interface InvoicingSubscriptionInvoiceEstimate {
|
|
55
66
|
amountDue: Amount;
|
|
56
67
|
couponDiscountTotal: Amount;
|
|
68
|
+
/** Item- and invoice-level coupons, one row each; they sum to `couponDiscountTotal`. */
|
|
69
|
+
coupons: InvoicingSubscriptionEstimateCoupon[];
|
|
57
70
|
/** Refundable credits plus excess payments; promotional credits are separate. */
|
|
58
71
|
creditsApplied: Amount;
|
|
59
72
|
grossSubTotal: Amount;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zeniai/client-epic-state",
|
|
3
|
-
"version": "5.2.
|
|
3
|
+
"version": "5.2.82",
|
|
4
4
|
"description": "Shared module between Web & Mobile containing required abstractions for state management, async network communication. ",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"module": "lib/esm/index.js",
|