payment-kit 1.15.18 → 1.15.20

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.
@@ -4,8 +4,8 @@ import pick from 'lodash/pick';
4
4
  import pWaitFor from 'p-wait-for';
5
5
  import type Stripe from 'stripe';
6
6
 
7
- import { checkUsageReportEmpty } from '@api/libs/subscription';
8
- import { createEvent } from '@api/libs/audit';
7
+ import { checkUsageReportEmpty } from '../../../libs/subscription';
8
+ import { createEvent } from '../../../libs/audit';
9
9
  import { getLock } from '../../../libs/lock';
10
10
  import logger from '../../../libs/logger';
11
11
  import {
@@ -1,5 +1,5 @@
1
- import { getOwnerDid } from '@api/libs/util';
2
1
  import prettyMsI18n from 'pretty-ms-i18n';
2
+ import { getOwnerDid } from '../../util';
3
3
  import { translate } from '../../../locales';
4
4
  import { Subscription } from '../../../store/models';
5
5
  import type { BaseEmailTemplate, BaseEmailTemplateType } from './base';
@@ -1,6 +1,6 @@
1
1
  import { Op } from 'sequelize';
2
2
 
3
- import { getInvoiceShouldPayTotal } from '@api/libs/invoice';
3
+ import { getInvoiceShouldPayTotal } from '../libs/invoice';
4
4
  import { batchHandleStripeInvoices } from '../integrations/stripe/resource';
5
5
  import { createEvent } from '../libs/audit';
6
6
  import dayjs from '../libs/dayjs';
@@ -1,6 +1,6 @@
1
1
  import type { LiteralUnion } from 'type-fest';
2
2
 
3
- import { createEvent } from '@api/libs/audit';
3
+ import { createEvent } from '../libs/audit';
4
4
  import { ensurePassportRevoked } from '../integrations/blocklet/passport';
5
5
  import { batchHandleStripeSubscriptions } from '../integrations/stripe/resource';
6
6
  import { wallet } from '../libs/auth';
@@ -863,8 +863,7 @@ events.on('customer.subscription.deleted', (subscription: Subscription) => {
863
863
  });
864
864
 
865
865
  events.on('customer.subscription.upgraded', async (subscription: Subscription) => {
866
- await subscriptionQueue.delete(subscription.id);
867
- await addSubscriptionJob(subscription, 'cancel', true, subscription.current_period_end);
866
+ await addSubscriptionJob(subscription, 'cycle', true, subscription.current_period_end);
868
867
  logger.info('subscription cycle job rescheduled after upgrade', {
869
868
  subscription: subscription.id,
870
869
  runAt: subscription.current_period_end,
@@ -8,7 +8,9 @@ import { createListParamSchema, MetadataSchema } from '../libs/api';
8
8
  import { authenticate } from '../libs/security';
9
9
  import { expandLineItems } from '../libs/session';
10
10
  import { formatMetadata } from '../libs/util';
11
- import { Price, Product, SubscriptionItem, UsageRecord } from '../store/models';
11
+ import { Price, Product, Subscription, SubscriptionItem, UsageRecord } from '../store/models';
12
+ import { forwardUsageRecordToStripe } from '../integrations/stripe/resource';
13
+ import { usageRecordQueue } from '../queues/usage-record';
12
14
 
13
15
  const router = Router();
14
16
  const auth = authenticate<SubscriptionItem>({ component: true, roles: ['owner', 'admin'] });
@@ -164,19 +166,55 @@ router.post('/:id/add-usage-quantity', auth, async (req, res) => {
164
166
  return res.status(403).json({ error: 'add usage quantity not allowed in livemode' });
165
167
  }
166
168
 
167
- const subscriptionItem = await SubscriptionItem.findByPk(req.params.id);
168
- if (!subscriptionItem) {
169
- return res.status(404).json({ error: `SubscriptionItem(${req.params.id}) item not found` });
169
+ const quantity = Number(req.body.quantity);
170
+ if (quantity <= 0) {
171
+ return res.status(400).json({ error: 'quantity must be positive' });
170
172
  }
171
173
 
172
- await UsageRecord.create({
173
- livemode: Boolean(livemode),
174
- subscription_item_id: subscriptionItem.id,
175
- quantity: req.body.quantity,
176
- timestamp: dayjs().unix(),
177
- } as UsageRecord);
174
+ try {
175
+ const subscriptionItem = await SubscriptionItem.findByPk(req.params.id);
176
+ if (!subscriptionItem) {
177
+ return res.status(404).json({ error: `SubscriptionItem(${req.params.id}) item not found` });
178
+ }
179
+ const subscription = await Subscription.findByPk(subscriptionItem.subscription_id);
180
+ if (!subscription) {
181
+ return res.status(400).json({ error: `Subscription not found: ${subscriptionItem.subscription_id}` });
182
+ }
183
+
184
+ if (subscription.isImmutable()) {
185
+ return res.status(400).json({ error: `subscription(${subscription.id}) is immutable` });
186
+ }
187
+
188
+ const now = dayjs().unix();
189
+
190
+ if (now < subscription.current_period_start || now > subscription.current_period_end) {
191
+ return res.status(400).json({ error: 'timestamp must be within the current period' });
192
+ }
193
+
194
+ const usageRecord = await UsageRecord.create({
195
+ livemode: Boolean(livemode),
196
+ subscription_item_id: subscriptionItem.id,
197
+ quantity,
198
+ timestamp: now,
199
+ } as UsageRecord);
200
+
201
+ if (subscription.billing_thresholds?.amount_gte) {
202
+ usageRecordQueue.push({
203
+ id: `usage-${subscription.id}`,
204
+ job: { subscriptionId: subscription.id, subscriptionItemId: subscriptionItem.id },
205
+ });
206
+ }
178
207
 
179
- return res.json();
208
+ await forwardUsageRecordToStripe(subscriptionItem, {
209
+ quantity,
210
+ timestamp: now,
211
+ action: 'increment',
212
+ });
213
+ return res.json(usageRecord);
214
+ } catch (err) {
215
+ console.error(err);
216
+ return res.status(400).json({ error: `Failed to add usage quantity: ${err.message}` });
217
+ }
180
218
  });
181
219
 
182
220
  export default router;
package/blocklet.yml CHANGED
@@ -14,7 +14,7 @@ repository:
14
14
  type: git
15
15
  url: git+https://github.com/blocklet/payment-kit.git
16
16
  specVersion: 1.2.8
17
- version: 1.15.18
17
+ version: 1.15.20
18
18
  logo: logo.png
19
19
  files:
20
20
  - dist
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "payment-kit",
3
- "version": "1.15.18",
3
+ "version": "1.15.20",
4
4
  "scripts": {
5
5
  "dev": "blocklet dev --open",
6
6
  "eject": "vite eject",
@@ -52,7 +52,7 @@
52
52
  "@arcblock/validator": "^1.18.135",
53
53
  "@blocklet/js-sdk": "^1.16.32",
54
54
  "@blocklet/logger": "^1.16.32",
55
- "@blocklet/payment-react": "1.15.18",
55
+ "@blocklet/payment-react": "1.15.20",
56
56
  "@blocklet/sdk": "^1.16.32",
57
57
  "@blocklet/ui-react": "^2.10.45",
58
58
  "@blocklet/uploader": "^0.1.43",
@@ -118,7 +118,7 @@
118
118
  "devDependencies": {
119
119
  "@abtnode/types": "^1.16.32",
120
120
  "@arcblock/eslint-config-ts": "^0.3.2",
121
- "@blocklet/payment-types": "1.15.18",
121
+ "@blocklet/payment-types": "1.15.20",
122
122
  "@types/cookie-parser": "^1.4.7",
123
123
  "@types/cors": "^2.8.17",
124
124
  "@types/debug": "^4.1.12",
@@ -160,5 +160,5 @@
160
160
  "parser": "typescript"
161
161
  }
162
162
  },
163
- "gitHead": "f57a3e622d9701fa0421f1266efc2fd92bd84780"
163
+ "gitHead": "0499ea79c00bb48d7a2479af589c21698c6388a0"
164
164
  }
package/tsconfig.json CHANGED
@@ -100,8 +100,8 @@
100
100
  "skipLibCheck": true, /* Skip type checking all .d.ts files. */
101
101
  "baseUrl": "./",
102
102
  "paths": {
103
- "@app/*": ["./src/*"],
104
- "@api/*": ["./api/src/*"],
103
+ // "@app/*": ["./src/*"],
104
+ // "@api/*": ["./api/src/*"],
105
105
  }
106
106
  }
107
107
  }