payment-kit 1.21.13 → 1.21.15

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.
Files changed (56) hide show
  1. package/api/src/crons/payment-stat.ts +31 -23
  2. package/api/src/libs/invoice.ts +29 -4
  3. package/api/src/libs/product.ts +28 -4
  4. package/api/src/routes/checkout-sessions.ts +46 -1
  5. package/api/src/routes/index.ts +2 -0
  6. package/api/src/routes/invoices.ts +63 -2
  7. package/api/src/routes/payment-stats.ts +244 -22
  8. package/api/src/routes/products.ts +3 -0
  9. package/api/src/routes/tax-rates.ts +220 -0
  10. package/api/src/store/migrations/20251001-add-tax-code-to-products.ts +20 -0
  11. package/api/src/store/migrations/20251001-create-tax-rates.ts +17 -0
  12. package/api/src/store/migrations/20251007-relate-tax-rate-to-invoice.ts +24 -0
  13. package/api/src/store/migrations/20251009-add-tax-behavior.ts +21 -0
  14. package/api/src/store/models/index.ts +3 -0
  15. package/api/src/store/models/invoice-item.ts +10 -0
  16. package/api/src/store/models/price.ts +7 -0
  17. package/api/src/store/models/product.ts +7 -0
  18. package/api/src/store/models/tax-rate.ts +352 -0
  19. package/api/tests/models/tax-rate.spec.ts +777 -0
  20. package/blocklet.yml +2 -2
  21. package/package.json +6 -6
  22. package/public/currencies/dollar.png +0 -0
  23. package/src/components/collapse.tsx +3 -2
  24. package/src/components/drawer-form.tsx +2 -1
  25. package/src/components/invoice/list.tsx +38 -3
  26. package/src/components/invoice/table.tsx +48 -2
  27. package/src/components/metadata/form.tsx +2 -2
  28. package/src/components/payment-intent/list.tsx +19 -3
  29. package/src/components/payouts/list.tsx +19 -3
  30. package/src/components/price/currency-select.tsx +105 -48
  31. package/src/components/price/form.tsx +3 -1
  32. package/src/components/product/form.tsx +79 -5
  33. package/src/components/refund/list.tsx +20 -3
  34. package/src/components/subscription/items/actions.tsx +25 -15
  35. package/src/components/subscription/list.tsx +15 -3
  36. package/src/components/tax/actions.tsx +140 -0
  37. package/src/components/tax/filter-toolbar.tsx +230 -0
  38. package/src/components/tax/tax-code-select.tsx +633 -0
  39. package/src/components/tax/tax-rate-form.tsx +177 -0
  40. package/src/components/tax/tax-utils.ts +38 -0
  41. package/src/components/tax/taxCodes.json +10882 -0
  42. package/src/components/uploader.tsx +3 -0
  43. package/src/hooks/cache-state.ts +84 -0
  44. package/src/locales/en.tsx +152 -0
  45. package/src/locales/zh.tsx +149 -0
  46. package/src/pages/admin/billing/invoices/detail.tsx +1 -1
  47. package/src/pages/admin/index.tsx +2 -0
  48. package/src/pages/admin/overview.tsx +1114 -322
  49. package/src/pages/admin/products/vendors/index.tsx +4 -2
  50. package/src/pages/admin/tax/create.tsx +104 -0
  51. package/src/pages/admin/tax/detail.tsx +476 -0
  52. package/src/pages/admin/tax/edit.tsx +126 -0
  53. package/src/pages/admin/tax/index.tsx +86 -0
  54. package/src/pages/admin/tax/list.tsx +334 -0
  55. package/src/pages/customer/subscription/change-payment.tsx +1 -1
  56. package/src/pages/home.tsx +6 -3
@@ -3,6 +3,7 @@ import { Stack, styled } from '@mui/system';
3
3
  import { lazy, Suspense, useCallback, useEffect, useRef } from 'react';
4
4
  import { CloudUpload, Delete, Edit } from '@mui/icons-material';
5
5
  import { createPortal } from 'react-dom';
6
+ import { useLocaleContext } from '@arcblock/ux/lib/Locale/context';
6
7
 
7
8
  const UploaderComponent = lazy(() =>
8
9
  import(/* webpackChunkName: "blocklet-uploader" */ '@blocklet/uploader').then((res) => ({
@@ -27,6 +28,7 @@ export default function Uploader({
27
28
  allowedFileExts = ['.png', '.jpeg', '.webp', '.svg', '.jpg'],
28
29
  disabled = false,
29
30
  }: Props) {
31
+ const { locale } = useLocaleContext();
30
32
  const uploaderRef = useRef<any>(null);
31
33
  const handleOpen = useCallback(() => {
32
34
  if (!uploaderRef.current) return;
@@ -72,6 +74,7 @@ export default function Uploader({
72
74
  uploader: '/api/uploads',
73
75
  companion: '/api/companion',
74
76
  }}
77
+ locale={locale}
75
78
  />
76
79
  </Suspense>
77
80
  );
@@ -0,0 +1,84 @@
1
+ import { useCallback, useState } from 'react';
2
+
3
+ type StorageType = 'localStorage' | 'sessionStorage' | 'cookie';
4
+
5
+ interface CacheStateOptions<T> {
6
+ defaultValue: T;
7
+ storage?: StorageType;
8
+ getUrlParams?: () => Partial<T>;
9
+ clearUrlParams?: () => void;
10
+ }
11
+
12
+ const getStorageValue = <T>(key: string, storage: StorageType): T | undefined => {
13
+ try {
14
+ if (storage === 'cookie') {
15
+ const matches = document.cookie.match(
16
+ new RegExp(`(?:^|; )${key.replace(/([.$?*|{}()[\]\\/+^])/g, '\\$1')}=([^;]*)`)
17
+ );
18
+ return matches?.[1] ? JSON.parse(decodeURIComponent(matches[1])) : undefined;
19
+ }
20
+ const storageObj = storage === 'sessionStorage' ? sessionStorage : localStorage;
21
+ const value = storageObj.getItem(key);
22
+ return value ? JSON.parse(value) : undefined;
23
+ } catch {
24
+ return undefined;
25
+ }
26
+ };
27
+
28
+ const setStorageValue = <T>(key: string, value: T, storage: StorageType): void => {
29
+ try {
30
+ const serialized = JSON.stringify(value);
31
+ if (storage === 'cookie') {
32
+ document.cookie = `${encodeURIComponent(key)}=${encodeURIComponent(serialized)}; path=/`;
33
+ return;
34
+ }
35
+ const storageObj = storage === 'sessionStorage' ? sessionStorage : localStorage;
36
+ storageObj.setItem(key, serialized);
37
+ } catch (error) {
38
+ console.error(`Failed to set ${storage} value:`, error);
39
+ }
40
+ };
41
+
42
+ const getInitialValue = <T>(
43
+ key: string,
44
+ storage: StorageType,
45
+ defaultValue: T,
46
+ getUrlParams?: () => Partial<T>,
47
+ clearUrlParams?: () => void
48
+ ): T => {
49
+ const cachedValue = getStorageValue<T>(key, storage);
50
+ const urlParams = getUrlParams?.();
51
+
52
+ if (urlParams && Object.keys(urlParams).length > 0) {
53
+ const mergedValue = {
54
+ ...(cachedValue || defaultValue),
55
+ ...urlParams,
56
+ };
57
+ setStorageValue(key, mergedValue, storage);
58
+ clearUrlParams?.();
59
+ return mergedValue;
60
+ }
61
+
62
+ return cachedValue !== undefined ? cachedValue : defaultValue;
63
+ };
64
+
65
+ export const useCacheState = <T = any>(key: string, options: CacheStateOptions<T>) => {
66
+ const { defaultValue, storage = 'localStorage', getUrlParams, clearUrlParams } = options;
67
+
68
+ const [state, setState] = useState<T>(() =>
69
+ getInitialValue(key, storage, defaultValue, getUrlParams, clearUrlParams)
70
+ );
71
+
72
+ const setStateAndStorage = useCallback(
73
+ (value: T | ((prev: T) => T)) => {
74
+ setState((prevState) => {
75
+ const nextState = typeof value === 'function' ? (value as (prev: T) => T)(prevState) : value;
76
+ setStorageValue(key, nextState, storage);
77
+ return nextState;
78
+ });
79
+ },
80
+ [key, storage]
81
+ );
82
+
83
+ return [state, setStateAndStorage] as const;
84
+ };
@@ -5,6 +5,7 @@ export default flat({
5
5
  redirecting: 'Redirecting...',
6
6
  title: 'Name',
7
7
  estimated: 'Estimated',
8
+ total: 'Total',
8
9
  active: 'Active',
9
10
  inactive: 'Inactive',
10
11
  metadata: {
@@ -41,18 +42,28 @@ export default flat({
41
42
  quickStart: 'Quick Start Guides',
42
43
  advancedFeatures: 'Advanced Features',
43
44
  quickStarts: 'Quick Starts',
45
+ homeTagline: 'A decentralized Stripe-like payment solution for Blocklets',
46
+ adminDashboard: 'Admin Dashboard',
47
+ customerPortal: 'Customer Portal',
44
48
  copy: 'Copy',
45
49
  copied: 'Copied',
46
50
  copySuccess: 'Copied successfully',
47
51
  copyFailed: 'Copy failed',
48
52
  copyTip: 'Please copy manually',
49
53
  save: 'Save',
54
+ saving: 'Saving...',
50
55
  cancel: 'Cancel',
56
+ back: 'Back',
51
57
  know: 'I Know',
52
58
  confirm: 'Confirm',
53
59
  edit: 'Edit',
60
+ view: 'View',
61
+ select: 'Select',
62
+ clear: 'Clear',
54
63
  delete: 'Delete',
55
64
  deleting: 'Deleting...',
65
+ activate: 'Activate',
66
+ deactivate: 'Deactivate',
56
67
  yes: 'Yes',
57
68
  no: 'No',
58
69
  never: 'Never',
@@ -95,6 +106,7 @@ export default flat({
95
106
  viewInvoice: 'View Invoice',
96
107
  viewSourceData: 'View Source',
97
108
  goToConfigure: 'Go to Configure',
109
+ noData: 'No data',
98
110
  },
99
111
  notification: {
100
112
  preferences: {
@@ -120,6 +132,52 @@ export default flat({
120
132
  metrics: 'Metrics',
121
133
  attention: 'Attention',
122
134
  overview: 'Overview',
135
+ overviewPage: {
136
+ financialIndicatorsTitle: 'Financial Indicators',
137
+ businessMonitoringTitle: 'Business Monitoring',
138
+ filters: {
139
+ dateRange: 'Select Date Range',
140
+ currencyLabel: 'Currencies',
141
+ productLabel: 'Products',
142
+ regionLabel: 'Regions',
143
+ allCurrencies: 'All Currencies',
144
+ allProducts: 'All Products',
145
+ allRegions: 'All Regions',
146
+ },
147
+ financialIndicators: {
148
+ totalIncome: {
149
+ title: 'Total Income',
150
+ subtitle: "User's actual payment",
151
+ },
152
+ costOfGoods: {
153
+ title: 'Cost of Goods',
154
+ subtitle: 'Supplier share',
155
+ },
156
+ netRevenue: {
157
+ title: 'Net Revenue',
158
+ subtitle: 'Revenue after vendor costs',
159
+ },
160
+ promotionCost: {
161
+ title: 'Promotion Cost',
162
+ subtitle: 'Discount',
163
+ },
164
+ taxedRevenue: {
165
+ title: 'Taxed Revenue',
166
+ subtitle: 'Revenue with tax',
167
+ },
168
+ },
169
+ charts: {
170
+ title: 'Transaction Trends',
171
+ payments: 'Payments',
172
+ payouts: 'Payouts',
173
+ refunds: 'Refunds',
174
+ allCurrencies: 'All currencies',
175
+ },
176
+ metrics: {
177
+ transaction: 'Transaction Metrics',
178
+ essential: 'Essential Metrics',
179
+ },
180
+ },
123
181
  payments: 'Payments',
124
182
  connections: 'Connections',
125
183
  back: 'Back',
@@ -136,6 +194,69 @@ export default flat({
136
194
  invoiceItems: 'Invoice Items',
137
195
  pricing: 'Pricing',
138
196
  coupons: 'Coupons',
197
+ tax: 'Tax',
198
+ taxRates: 'Tax Rates',
199
+ taxRate: {
200
+ create: 'Create Tax Rate',
201
+ createTitle: 'Create Tax Rate',
202
+ createAction: 'Add Tax Rate',
203
+ created: 'Tax rate created successfully',
204
+ updated: 'Tax rate updated successfully',
205
+ deleted: 'Tax rate deleted successfully',
206
+ label: 'Tax Rate',
207
+ view: 'View Tax Rate',
208
+ displayName: 'Display Name',
209
+ displayNamePlaceholder: 'Name shown on invoices and reports',
210
+ displayNameAuto: 'Auto-generated if left empty',
211
+ displayNameRequired: 'Display name is required',
212
+ description: 'Description',
213
+ descriptionPlaceholder: 'Optional description',
214
+ country: 'Country',
215
+ countryRequired: 'Country is required',
216
+ state: 'State/Province',
217
+ postalCode: 'Postal Code',
218
+ taxCode: 'Product Tax Code',
219
+ taxCodeDescription:
220
+ 'Tax codes are used to calculate automatic taxes based on product type and location. You can ',
221
+ taxCodeDescriptionLink: 'manage tax rates',
222
+ taxCodeDescriptionSuffix: ' to create custom tax rates for specific tax codes and regions.',
223
+ selectTaxCode: 'Select product tax code',
224
+ percentage: 'Tax Rate (%)',
225
+ percentageRequired: 'Tax rate percentage is required',
226
+ percentageMin: 'Tax rate must be 0% or higher',
227
+ percentageMax: 'Tax rate must be less than 100%',
228
+ active: 'Active by default',
229
+ location: 'Region',
230
+ advanced: 'Advanced options',
231
+ search: 'Search tax rates',
232
+ searchCountry: 'Search country',
233
+ back: 'Back to tax rates',
234
+ associatedInvoices: 'Related Invoices',
235
+ deleteTitle: 'Delete Tax Rate',
236
+ deleteMessage: 'Are you sure you want to delete tax rate “{name}”? This action cannot be undone.',
237
+ deactivateTitle: 'Deactivate Tax Rate',
238
+ deactivateMessage: 'Deactivate “{name}”? It will no longer apply automatically to invoices.',
239
+ activateTitle: 'Activate Tax Rate',
240
+ activateMessage: 'Activate “{name}”? It will be available for future invoices.',
241
+ createTitleShort: 'Add tax rate',
242
+ edit: 'Edit',
243
+ editTitle: 'Edit Tax Rate',
244
+ selectTaxCodeHint: "We'll use this tax code to calculate automatic tax on invoices.",
245
+ searchPlaceholder: 'Search by product or tax code',
246
+ previewPlaceholder: 'Select a tax code to see details.',
247
+ usePreset: 'Use preset',
248
+ noPreset: 'No preset selected',
249
+ noSuggestions: 'No tax codes match your search.',
250
+ relatedInvoiceNum: 'Related Invoices',
251
+ notUsed: 'Not used',
252
+ taxCodeLabel: 'Tax code: {code}',
253
+ types: {
254
+ general: 'General',
255
+ digital: 'Digital products',
256
+ services: 'Services',
257
+ physical: 'Physical goods',
258
+ },
259
+ },
139
260
  pricingTables: 'Pricing tables',
140
261
  vendors: 'Vendors',
141
262
  billing: 'Billing',
@@ -449,8 +570,12 @@ export default flat({
449
570
  type: {
450
571
  label: 'Product Type',
451
572
  service: 'Service',
573
+ serviceDesc: 'Digital services or subscriptions',
452
574
  credit: 'Credit',
575
+ creditDesc: 'Credit top-up product for credit-based billing scenarios',
576
+ creditDescLink: 'Create meters first',
453
577
  good: 'Good',
578
+ goodDesc: 'Physical products or tangible goods',
454
579
  },
455
580
  vendorConfig: {
456
581
  title: 'Vendor Configuration',
@@ -489,6 +614,7 @@ export default flat({
489
614
  additional: 'Additional options',
490
615
  model: 'Pricing model',
491
616
  amount: 'Price',
617
+ amountDescription: 'This is the tax-inclusive price that customers will pay.',
492
618
  locked: 'This price is locked because it is used by a subscription or a payment.',
493
619
  amountTip: 'Choose recurring for subscriptions and one-time for everything else.',
494
620
  duplicate: 'Duplicate price',
@@ -898,6 +1024,11 @@ export default flat({
898
1024
  view: 'View payment detail',
899
1025
  empty: 'No payment intent',
900
1026
  refund: 'Refund payment',
1027
+ status: {
1028
+ active: 'Active',
1029
+ paid: 'Paid',
1030
+ succeeded: 'Succeeded',
1031
+ },
901
1032
  received: 'Received',
902
1033
  attention: 'Failed payments',
903
1034
  refundError: 'Failed to refund payment',
@@ -928,6 +1059,11 @@ export default flat({
928
1059
  view: 'View payout',
929
1060
  empty: 'No payout',
930
1061
  attention: 'Failed payouts',
1062
+ status: {
1063
+ active: 'Active',
1064
+ paid: 'Paid',
1065
+ succeeded: 'Succeeded',
1066
+ },
931
1067
  },
932
1068
  paymentMethod: {
933
1069
  _name: 'Payment Method',
@@ -1074,7 +1210,13 @@ export default flat({
1074
1210
  invoice: {
1075
1211
  view: 'View invoice',
1076
1212
  attention: 'Uncollectible invoices',
1213
+ metric: 'Paid invoices',
1077
1214
  name: 'Invoice',
1215
+ status: {
1216
+ active: 'Active',
1217
+ paid: 'Paid',
1218
+ succeeded: 'Succeeded',
1219
+ },
1078
1220
  from: 'Billed from',
1079
1221
  empty: 'No invoices',
1080
1222
  number: 'Invoice Number',
@@ -1181,6 +1323,11 @@ export default flat({
1181
1323
  view: 'View subscription',
1182
1324
  name: 'Subscription',
1183
1325
  empty: 'No subscriptions',
1326
+ status: {
1327
+ active: 'Active',
1328
+ paid: 'Paid',
1329
+ succeeded: 'Succeeded',
1330
+ },
1184
1331
  viewAll: 'View all subscriptions',
1185
1332
  noActiveEmpty: 'You currently have no active subscriptions. You can choose to view your subscription history.',
1186
1333
  includedServices: 'Included Services',
@@ -1389,6 +1536,11 @@ export default flat({
1389
1536
  name: 'Refunds',
1390
1537
  view: 'View refund detail',
1391
1538
  attention: 'Failed refunds',
1539
+ status: {
1540
+ active: 'Active',
1541
+ paid: 'Paid',
1542
+ succeeded: 'Succeeded',
1543
+ },
1392
1544
  },
1393
1545
  usageRecord: {
1394
1546
  empty: 'No usage records',
@@ -5,6 +5,7 @@ export default flat({
5
5
  redirecting: '跳转中...',
6
6
  title: '名称',
7
7
  estimated: '预估',
8
+ total: '总量',
8
9
  active: '生效中',
9
10
  metadata: {
10
11
  label: '元数据',
@@ -39,18 +40,28 @@ export default flat({
39
40
  quickStart: '快速入门指南',
40
41
  advancedFeatures: '高级功能',
41
42
  quickStarts: '快速入门',
43
+ homeTagline: '为 Blocklet 构建的去中心化支付解决方案',
44
+ adminDashboard: '管理后台',
45
+ customerPortal: '客户门户',
42
46
  copy: '复制',
43
47
  copied: '已复制',
44
48
  copySuccess: '复制成功',
45
49
  copyFailed: '复制失败',
46
50
  copyTip: '请手动复制',
47
51
  save: '保存',
52
+ saving: '保存中...',
48
53
  cancel: '取消',
54
+ back: '返回',
49
55
  know: '知道了',
50
56
  confirm: '确认',
51
57
  edit: '编辑',
58
+ view: '查看',
59
+ select: '选择',
60
+ clear: '清除',
52
61
  delete: '删除',
53
62
  deleting: '删除中...',
63
+ activate: '启用',
64
+ deactivate: '停用',
54
65
  yes: '是',
55
66
  no: '否',
56
67
  never: '永不',
@@ -94,6 +105,7 @@ export default flat({
94
105
  viewInvoice: '查看账单',
95
106
  viewSourceData: '查看来源',
96
107
  goToConfigure: '前往配置',
108
+ noData: '暂无数据',
97
109
  },
98
110
  notification: {
99
111
  preferences: {
@@ -119,6 +131,52 @@ export default flat({
119
131
  metrics: '指标',
120
132
  attention: '注意',
121
133
  overview: '总览',
134
+ overviewPage: {
135
+ financialIndicatorsTitle: '财务指标',
136
+ businessMonitoringTitle: '业务监控',
137
+ filters: {
138
+ dateRange: '选择日期范围',
139
+ currencyLabel: '币种',
140
+ productLabel: '产品',
141
+ regionLabel: '地区',
142
+ allCurrencies: '全部币种',
143
+ allProducts: '全部产品',
144
+ allRegions: '全部地区',
145
+ },
146
+ financialIndicators: {
147
+ totalIncome: {
148
+ title: '总收入',
149
+ subtitle: '用户实际支付',
150
+ },
151
+ costOfGoods: {
152
+ title: '进货成本',
153
+ subtitle: '供应商分成',
154
+ },
155
+ netRevenue: {
156
+ title: '净收入',
157
+ subtitle: '扣除供货成本后的收入',
158
+ },
159
+ promotionCost: {
160
+ title: '促销成本',
161
+ subtitle: '折扣',
162
+ },
163
+ taxedRevenue: {
164
+ title: '含税收入',
165
+ subtitle: '包含税费的收入',
166
+ },
167
+ },
168
+ charts: {
169
+ title: '交易趋势',
170
+ payments: '付款',
171
+ payouts: '出款',
172
+ refunds: '退款',
173
+ allCurrencies: '全部币种',
174
+ },
175
+ metrics: {
176
+ transaction: '交易指标',
177
+ essential: '关键指标',
178
+ },
179
+ },
122
180
  payments: '支付管理',
123
181
  connections: '连接',
124
182
  back: '返回',
@@ -134,6 +192,67 @@ export default flat({
134
192
  products: '产品定价',
135
193
  invoiceItems: '账单明细',
136
194
  coupons: '优惠券',
195
+ tax: '税务',
196
+ taxRates: '税率',
197
+ taxRate: {
198
+ create: '创建税率',
199
+ createTitle: '新建税率',
200
+ createAction: '添加税率',
201
+ created: '税率创建成功',
202
+ updated: '税率更新成功',
203
+ deleted: '税率删除成功',
204
+ label: '税率',
205
+ view: '查看税率',
206
+ displayName: '显示名称',
207
+ displayNamePlaceholder: '显示在账单和报表上的名称',
208
+ displayNameAuto: '留空则自动生成',
209
+ displayNameRequired: '请填写显示名称',
210
+ description: '描述',
211
+ descriptionPlaceholder: '可选描述信息',
212
+ country: '国家/地区',
213
+ countryRequired: '请选择国家/地区',
214
+ state: '州 / 省',
215
+ postalCode: '邮政编码',
216
+ taxCode: '产品税码',
217
+ taxCodeDescription: '产品税码用于根据产品类型和地区自动计算税费。您可以',
218
+ taxCodeDescriptionLink: '管理税率',
219
+ taxCodeDescriptionSuffix: '以创建针对特定税码和地区的自定义税率。',
220
+ selectTaxCode: '选择产品税码',
221
+ percentage: '税率 (%)',
222
+ percentageRequired: '请填写税率',
223
+ percentageMin: '税率需大于或等于 0%',
224
+ percentageMax: '税率需小于 100%',
225
+ active: '默认启用',
226
+ location: '适用区域',
227
+ advanced: '高级选项',
228
+ search: '搜索税率',
229
+ searchCountry: '搜索国家/地区',
230
+ back: '返回税率列表',
231
+ associatedInvoices: '关联账单',
232
+ deleteTitle: '删除税率',
233
+ deleteMessage: '确定要删除税率“{name}”吗?该操作无法撤销。',
234
+ deactivateTitle: '停用税率',
235
+ deactivateMessage: '确定要停用“{name}”吗?停用后将不再自动应用。',
236
+ activateTitle: '启用税率',
237
+ activateMessage: '确定要启用"{name}"吗?启用后可用于新的账单。',
238
+ edit: '编辑',
239
+ editTitle: '编辑税率',
240
+ selectTaxCodeHint: '税率将用于自动计算账单中的税费。',
241
+ searchPlaceholder: '按产品或税码搜索',
242
+ previewPlaceholder: '请选择税码以查看详情。',
243
+ usePreset: '默认税码',
244
+ noPreset: '暂无默认税码',
245
+ noSuggestions: '没有符合搜索条件的税码。',
246
+ relatedInvoiceNum: '关联账单数',
247
+ notUsed: '未使用',
248
+ taxCodeLabel: '税码:{code}',
249
+ types: {
250
+ general: '通用类别',
251
+ digital: '数字产品',
252
+ services: '服务类',
253
+ physical: '实物商品',
254
+ },
255
+ },
137
256
  pricing: '定价',
138
257
  pricingTables: '定价表',
139
258
  vendors: '供应商',
@@ -422,8 +541,12 @@ export default flat({
422
541
  type: {
423
542
  label: '产品类型',
424
543
  service: '服务',
544
+ serviceDesc: '数字服务或订阅',
425
545
  credit: 'Credit',
546
+ creditDesc: '用于基于 Credit 计费场景的充值产品',
547
+ creditDescLink: '请先创建计量器',
426
548
  good: '商品',
549
+ goodDesc: '实体商品或有形产品',
427
550
  },
428
551
  vendorConfig: {
429
552
  title: '供应商配置',
@@ -460,6 +583,7 @@ export default flat({
460
583
  additional: '附加选项',
461
584
  model: '定价模型',
462
585
  amount: '价格',
586
+ amountDescription: '这是客户将支付的含税价格。',
463
587
  locked: '此价格已锁定,因为它用于订阅或支付。',
464
588
  amountTip: '对于订阅选择周期,对于其他所有选择一次性。',
465
589
  duplicate: '复制价格',
@@ -836,6 +960,11 @@ export default flat({
836
960
  view: '查看对外支付',
837
961
  empty: '没有记录',
838
962
  attention: '失败的对外支付',
963
+ status: {
964
+ active: '生效中',
965
+ paid: '已支付',
966
+ succeeded: '成功',
967
+ },
839
968
  },
840
969
  pricingTable: {
841
970
  view: '查看定价表',
@@ -864,6 +993,11 @@ export default flat({
864
993
  view: '查看付款详情',
865
994
  empty: '没有付款记录',
866
995
  refund: '退款',
996
+ status: {
997
+ active: '生效中',
998
+ paid: '已支付',
999
+ succeeded: '成功',
1000
+ },
867
1001
  received: '实收金额',
868
1002
  attention: '失败的付款',
869
1003
  refundError: '退款申请失败',
@@ -1048,6 +1182,11 @@ export default flat({
1048
1182
  name: '账单',
1049
1183
  from: '账单来自',
1050
1184
  empty: '没有账单',
1185
+ status: {
1186
+ active: '生效中',
1187
+ paid: '已支付',
1188
+ succeeded: '成功',
1189
+ },
1051
1190
  number: '账单编号',
1052
1191
  description: '账单说明',
1053
1192
  dueDate: '截止日期',
@@ -1153,6 +1292,11 @@ export default flat({
1153
1292
  view: '查看订阅',
1154
1293
  name: '订阅',
1155
1294
  empty: '没有订阅',
1295
+ status: {
1296
+ active: '生效中',
1297
+ paid: '已支付',
1298
+ succeeded: '成功',
1299
+ },
1156
1300
  viewAll: '查看历史订阅',
1157
1301
  noActiveEmpty: '您当前没有服务中的订阅,您可以选择查看历史订阅',
1158
1302
  includedServices: '包含的服务',
@@ -1351,6 +1495,11 @@ export default flat({
1351
1495
  name: '退款',
1352
1496
  attention: '失败的退款',
1353
1497
  view: '查看退款详情',
1498
+ status: {
1499
+ active: '生效中',
1500
+ paid: '已支付',
1501
+ succeeded: '成功',
1502
+ },
1354
1503
  },
1355
1504
  usageRecord: {
1356
1505
  empty: '用量记录为空',
@@ -389,7 +389,7 @@ export default function InvoiceDetail(props: { id: string }) {
389
389
  <Box className="section">
390
390
  <SectionHeader title={t('admin.summary')} />
391
391
  <Box className="section-body">
392
- <InvoiceTable invoice={data} emptyNodeText={t('empty.summary')} />
392
+ <InvoiceTable invoice={data} emptyNodeText={t('empty.summary')} mode="admin" />
393
393
  </Box>
394
394
  </Box>
395
395
  <Divider />
@@ -14,6 +14,7 @@ const groups = {
14
14
  customers: React.lazy(() => import('./customers/index')),
15
15
  products: React.lazy(() => import('./products/index')),
16
16
  billing: React.lazy(() => import('./billing/index')),
17
+ tax: React.lazy(() => import('./tax')),
17
18
  developers: React.lazy(() => import('./developers/index')),
18
19
  settings: React.lazy(() => import('./settings/index')),
19
20
  };
@@ -64,6 +65,7 @@ function Admin() {
64
65
  { label: t('admin.payments'), value: 'payments' },
65
66
  { label: t('admin.customers'), value: 'customers' },
66
67
  { label: t('admin.products'), value: 'products' },
68
+ { label: t('admin.tax'), value: 'tax' },
67
69
  { label: t('admin.billing'), value: 'billing' },
68
70
  { label: t('admin.settings'), value: 'settings' },
69
71
  ];