From b4723c74d0a6eb5ef19e97efe64baedc5bbf19b7 Mon Sep 17 00:00:00 2001 From: Surafel Melese Date: Sat, 5 Aug 2023 15:53:44 +0300 Subject: [PATCH 01/11] feat: updated the table of schedules list and and payment list --- .../codegen.yml | 1 + .../package.json | 9 +- .../src/api/graphql-schemas.ts | 62 ++- .../src/api/schedule.service.ts | 29 +- .../api/stripe-subscription-payment.entity.ts | 31 ++ .../src/api/stripe-subscription.controller.ts | 35 +- .../src/api/stripe-subscription.service.ts | 55 ++ .../src/stripe-subscription.plugin.ts | 7 +- .../payments-component.html | 91 ++++ .../payments-component/payments.component.ts | 80 +++ .../src/ui/queries.ts | 31 +- .../schedules.component-2.html | 333 ++++++++++++ .../schedules.component-2.ts | 324 ++++++++++++ .../schedules.component.html | 214 ++++++++ .../schedules.component.scss | 0 .../schedules.component.ts | 253 ++++++++++ .../src/ui/schedules.component.ts | 476 ------------------ .../src/ui/schedules.module.ts | 21 - .../ui/stripe-subscription-shared.module.ts | 16 +- .../src/ui/stripe-subscription.module.ts | 27 + .../test/dev-server.ts | 2 + .../test/helpers.ts | 24 +- .../test/stripe-subscription.spec.ts | 6 +- .../yarn.lock | 124 +++-- 24 files changed, 1683 insertions(+), 568 deletions(-) create mode 100644 packages/vendure-plugin-stripe-subscription/src/api/stripe-subscription-payment.entity.ts create mode 100644 packages/vendure-plugin-stripe-subscription/src/ui/payments-component/payments-component.html create mode 100644 packages/vendure-plugin-stripe-subscription/src/ui/payments-component/payments.component.ts create mode 100644 packages/vendure-plugin-stripe-subscription/src/ui/schedules-component/schedules.component-2.html create mode 100644 packages/vendure-plugin-stripe-subscription/src/ui/schedules-component/schedules.component-2.ts create mode 100644 packages/vendure-plugin-stripe-subscription/src/ui/schedules-component/schedules.component.html rename packages/vendure-plugin-stripe-subscription/src/ui/{ => schedules-component}/schedules.component.scss (100%) create mode 100644 packages/vendure-plugin-stripe-subscription/src/ui/schedules-component/schedules.component.ts delete mode 100644 packages/vendure-plugin-stripe-subscription/src/ui/schedules.component.ts delete mode 100644 packages/vendure-plugin-stripe-subscription/src/ui/schedules.module.ts create mode 100644 packages/vendure-plugin-stripe-subscription/src/ui/stripe-subscription.module.ts diff --git a/packages/vendure-plugin-stripe-subscription/codegen.yml b/packages/vendure-plugin-stripe-subscription/codegen.yml index 54b45919..6bdd6d76 100644 --- a/packages/vendure-plugin-stripe-subscription/codegen.yml +++ b/packages/vendure-plugin-stripe-subscription/codegen.yml @@ -5,6 +5,7 @@ generates: plugins: - typescript - typescript-operations + - typed-document-node config: avoidOptionals: false scalars: diff --git a/packages/vendure-plugin-stripe-subscription/package.json b/packages/vendure-plugin-stripe-subscription/package.json index 7979eda6..9dc0e816 100644 --- a/packages/vendure-plugin-stripe-subscription/package.json +++ b/packages/vendure-plugin-stripe-subscription/package.json @@ -24,13 +24,14 @@ "@graphql-codegen/cli": "^2.4.0", "@graphql-codegen/typescript": "^2.4.8", "@graphql-codegen/typescript-operations": "^2.3.5", + "@graphql-codegen/typed-document-node": "^5.0.1", "@swc/core": "^1.3.59", "@types/localtunnel": "^2.0.1", "@types/nock": "^11.1.0", - "@vendure/admin-ui-plugin": "2.0.4", - "@vendure/core": "2.0.4", - "@vendure/testing": "2.0.4", - "@vendure/ui-devkit": "2.0.4", + "@vendure/admin-ui-plugin": "2.0.5", + "@vendure/core": "2.0.5", + "@vendure/testing": "2.0.5", + "@vendure/ui-devkit": "2.0.5", "copyfiles": "^2.4.1", "nock": "^13.2.9", "node-fetch": "^2.0.0", diff --git a/packages/vendure-plugin-stripe-subscription/src/api/graphql-schemas.ts b/packages/vendure-plugin-stripe-subscription/src/api/graphql-schemas.ts index ce04435f..d843b9d4 100644 --- a/packages/vendure-plugin-stripe-subscription/src/api/graphql-schemas.ts +++ b/packages/vendure-plugin-stripe-subscription/src/api/graphql-schemas.ts @@ -7,6 +7,17 @@ const _scalar = gql` scalar DateTime `; +const _interface = gql` + interface Node { + id: ID! + createdAt: DateTime + } + interface PaginatedList { + items: [Node!]! + totalItems: Int! + } +`; + const sharedTypes = gql` enum SubscriptionInterval { week @@ -18,7 +29,10 @@ const sharedTypes = gql` time_of_purchase fixed_startdate } - type StripeSubscriptionSchedule { + """ + For codegen to work this must implement Node + """ + type StripeSubscriptionSchedule implements Node { id: ID! createdAt: DateTime updatedAt: DateTime @@ -35,6 +49,20 @@ const sharedTypes = gql` useProration: Boolean autoRenew: Boolean } + """ + For codegen to work this must implement Node + """ + type StripeSubscriptionPayment implements Node { + id: ID! + createdAt: DateTime + updatedAt: DateTime + collectionMethod: String + charge: String + currency: String + orderCode: String + channelId: ID + subscriptionId: String + } input UpsertStripeSubscriptionScheduleInput { id: ID name: String! @@ -108,9 +136,39 @@ export const adminSchemaExtensions = gql` STRIPE_SUBSCRIPTION_NOTIFICATION } + """ + For codegen to work this must be non-empty + """ + input StripeSubscriptionPaymentListOptions { + skip: Int + } + + """ + For codegen to work this must be non-empty + """ + input StripeSubscriptionScheduleListOptions { + skip: Int + } + + type StripeSubscriptionPaymentList implements PaginatedList { + items: [StripeSubscriptionPayment!]! + totalItems: Int! + } + + type StripeSubscriptionScheduleList implements PaginatedList { + items: [StripeSubscriptionSchedule!]! + totalItems: Int! + } + extend type Query { - stripeSubscriptionSchedules: [StripeSubscriptionSchedule!]! + stripeSubscriptionSchedules( + options: StripeSubscriptionScheduleListOptions + ): StripeSubscriptionScheduleList! + stripeSubscriptionPayments( + options: StripeSubscriptionPaymentListOptions + ): StripeSubscriptionPaymentList! } + extend type Mutation { upsertStripeSubscriptionSchedule( input: UpsertStripeSubscriptionScheduleInput! diff --git a/packages/vendure-plugin-stripe-subscription/src/api/schedule.service.ts b/packages/vendure-plugin-stripe-subscription/src/api/schedule.service.ts index 26b4e366..8aeacd4a 100644 --- a/packages/vendure-plugin-stripe-subscription/src/api/schedule.service.ts +++ b/packages/vendure-plugin-stripe-subscription/src/api/schedule.service.ts @@ -1,12 +1,15 @@ import { Injectable } from '@nestjs/common'; import { ID, + ListQueryBuilder, RequestContext, TransactionalConnection, UserInputError, } from '@vendure/core'; import { StripeSubscriptionSchedule, + StripeSubscriptionScheduleList, + StripeSubscriptionScheduleListOptions, SubscriptionStartMoment, UpsertStripeSubscriptionScheduleInput, } from '../ui/generated/graphql'; @@ -15,18 +18,24 @@ import { Schedule } from './schedule.entity'; @Injectable() export class ScheduleService { - constructor(private connection: TransactionalConnection) {} + constructor( + private listQueryBuilder: ListQueryBuilder, + private connection: TransactionalConnection + ) {} async getSchedules( - ctx: RequestContext - ): Promise { - const schedules = await this.connection - .getRepository(ctx, Schedule) - .find({ where: { channelId: String(ctx.channelId) } }); - - return schedules.map((schedule) => { - return cloneSchedule(ctx, schedule); - }); + ctx: RequestContext, + options: StripeSubscriptionScheduleListOptions + ): Promise { + return this.listQueryBuilder + .build(Schedule, options, { ctx }) + .getManyAndCount() + .then(([items, totalItems]) => ({ + items: items.map((schedule) => { + return cloneSchedule(ctx, schedule); + }), + totalItems, + })); } async upsert( diff --git a/packages/vendure-plugin-stripe-subscription/src/api/stripe-subscription-payment.entity.ts b/packages/vendure-plugin-stripe-subscription/src/api/stripe-subscription-payment.entity.ts new file mode 100644 index 00000000..30a043e3 --- /dev/null +++ b/packages/vendure-plugin-stripe-subscription/src/api/stripe-subscription-payment.entity.ts @@ -0,0 +1,31 @@ +import { DeepPartial } from '@vendure/common/lib/shared-types'; +import { VendureEntity, ID } from '@vendure/core'; +import { Column, Entity } from 'typeorm'; + +@Entity() +export class StripeSubscriptionPayment extends VendureEntity { + constructor(input?: DeepPartial) { + super(input); + } + + @Column({ nullable: true }) + invoiceId!: string; + + @Column({ nullable: true }) + collectionMethod!: string; + + @Column({ nullable: true }) + charge!: string; + + @Column({ nullable: true }) + currency!: string; + + @Column({ nullable: true }) + orderCode!: string; + + @Column({ nullable: true }) + channelId!: string; + + @Column({ nullable: true }) + subscriptionId!: string; +} diff --git a/packages/vendure-plugin-stripe-subscription/src/api/stripe-subscription.controller.ts b/packages/vendure-plugin-stripe-subscription/src/api/stripe-subscription.controller.ts index 5b07747f..b0f25e31 100644 --- a/packages/vendure-plugin-stripe-subscription/src/api/stripe-subscription.controller.ts +++ b/packages/vendure-plugin-stripe-subscription/src/api/stripe-subscription.controller.ts @@ -11,8 +11,10 @@ import { Allow, Ctx, ID, + ListQueryOptions, Logger, OrderService, + PaginatedList, Permission, ProductService, RequestContext, @@ -22,9 +24,14 @@ import { Request } from 'express'; import { loggerCtx, PLUGIN_INIT_OPTIONS } from '../constants'; import { StripeSubscriptionPluginOptions } from '../stripe-subscription.plugin'; import { + QueryStripeSubscriptionPaymentsArgs, + StripeSubscriptionPaymentList, + StripeSubscriptionPaymentListOptions, StripeSubscriptionPricing, StripeSubscriptionPricingInput, StripeSubscriptionSchedule, + StripeSubscriptionScheduleList, + StripeSubscriptionScheduleListOptions, UpsertStripeSubscriptionScheduleInput, } from '../ui/generated/graphql'; import { ScheduleService } from './schedule.service'; @@ -34,6 +41,7 @@ import { OrderLineWithSubscriptionFields, VariantWithSubscriptionFields, } from './subscription-custom-fields'; +import { StripeSubscriptionPayment } from './stripe-subscription-payment.entity'; export type RequestWithRawBody = Request & { rawBody: any }; @@ -119,14 +127,27 @@ export class AdminPriceIncludesTaxResolver { @Resolver() export class AdminResolver { - constructor(private scheduleService: ScheduleService) {} + constructor( + private stripeSubscriptionService: StripeSubscriptionService, + private scheduleService: ScheduleService + ) {} @Allow(Permission.ReadSettings) @Query() async stripeSubscriptionSchedules( - @Ctx() ctx: RequestContext - ): Promise { - return this.scheduleService.getSchedules(ctx); + @Ctx() ctx: RequestContext, + @Args('options') options: StripeSubscriptionScheduleListOptions + ): Promise { + return this.scheduleService.getSchedules(ctx, options); + } + + @Allow(Permission.ReadSettings) + @Query() + async stripeSubscriptionPayments( + @Ctx() ctx: RequestContext, + @Args('options') options: StripeSubscriptionPaymentListOptions + ): Promise { + return this.stripeSubscriptionService.getPayments(ctx, options); } @Allow(Permission.UpdateSettings) @@ -227,6 +248,12 @@ export class StripeSubscriptionController { body, order ); + } else if (body.type === 'invoice.payment_action_required') { + await this.stripeSubscriptionService.handleInvoicePaymentFailed( + ctx, + body, + order + ); } Logger.info(`Successfully handled webhook ${body.type}`, loggerCtx); } catch (error) { diff --git a/packages/vendure-plugin-stripe-subscription/src/api/stripe-subscription.service.ts b/packages/vendure-plugin-stripe-subscription/src/api/stripe-subscription.service.ts index d1f1a5f8..99bb3a74 100644 --- a/packages/vendure-plugin-stripe-subscription/src/api/stripe-subscription.service.ts +++ b/packages/vendure-plugin-stripe-subscription/src/api/stripe-subscription.service.ts @@ -2,6 +2,7 @@ import { Injectable } from '@nestjs/common'; import { StockMovementType } from '@vendure/common/lib/generated-types'; import { ActiveOrderService, + Channel, ChannelService, CustomerService, EntityHydrator, @@ -9,15 +10,19 @@ import { EventBus, HistoryService, ID, + InternalServerError, JobQueue, JobQueueService, LanguageCode, + ListQueryBuilder, + ListQueryOptions, Logger, Order, OrderLine, OrderLineEvent, OrderService, OrderStateTransitionError, + PaginatedList, PaymentMethodService, ProductVariantService, RequestContext, @@ -36,6 +41,8 @@ import { } from './subscription-custom-fields'; import { StripeClient } from './stripe.client'; import { + StripeSubscriptionPaymentList, + StripeSubscriptionPaymentListOptions, StripeSubscriptionPricing, StripeSubscriptionPricingInput, } from '../ui/generated/graphql'; @@ -52,6 +59,7 @@ import { Cancellation } from '@vendure/core/dist/entity/stock-movement/cancellat import { Release } from '@vendure/core/dist/entity/stock-movement/release.entity'; import { randomUUID } from 'crypto'; import { hasSubscriptions } from './has-stripe-subscription-products-payment-checker'; +import { StripeSubscriptionPayment } from './stripe-subscription-payment.entity'; export interface StripeHandlerConfig { paymentMethodCode: string; @@ -84,6 +92,7 @@ export class StripeSubscriptionService { private entityHydrator: EntityHydrator, private channelService: ChannelService, private orderService: OrderService, + private listQueryBuilder: ListQueryBuilder, private historyService: HistoryService, private eventBus: EventBus, private jobQueueService: JobQueueService, @@ -392,6 +401,49 @@ export class StripeSubscriptionService { }; } + async saveStripeSubscriptionEvent( + ctx: RequestContext, + object: any + ): Promise { + const stripeSubscriptionPaymentRepo = this.connection.getRepository( + ctx, + StripeSubscriptionPayment + ); + const channelRepo = this.connection.getRepository(ctx, Channel); + const channelToken = + object.metadata?.channelToken || + object.lines?.data[0]?.metadata.channelToken; + const requestChannel = await channelRepo.findOne({ + where: { token: channelToken }, + }); + if (!requestChannel) { + throw new InternalServerError(`Channel with ${channelToken} not found`); + } + const newPayment = new StripeSubscriptionPayment(); + newPayment.channelId = requestChannel.id as string; + newPayment.charge = object?.charge; + newPayment.currency = object.currency || requestChannel.defaultCurrencyCode; + newPayment.collectionMethod = object.collection_method; + newPayment.invoiceId = object.id; + newPayment.orderCode = + object.metadata?.orderCode || object.lines?.data[0]?.metadata.orderCode; + newPayment.subscriptionId = object.subscription; + await stripeSubscriptionPaymentRepo.save(newPayment); + } + + async getPayments( + ctx: RequestContext, + options: StripeSubscriptionPaymentListOptions + ): Promise { + return this.listQueryBuilder + .build(StripeSubscriptionPayment, options, { ctx }) + .getManyAndCount() + .then(([items, totalItems]) => ({ + items, + totalItems, + })); + } + /** * Handle future subscription payments that come in after the initial payment intent */ @@ -412,6 +464,7 @@ export class StripeSubscriptionService { undefined, object.subscription ); + await this.saveStripeSubscriptionEvent(ctx, object); } /** @@ -434,6 +487,7 @@ export class StripeSubscriptionService { undefined, object.subscription ); + await this.saveStripeSubscriptionEvent(ctx, object); } /** @@ -446,6 +500,7 @@ export class StripeSubscriptionService { order: Order ): Promise { const { paymentMethodCode } = await this.getStripeHandler(ctx, order.id); + await this.saveStripeSubscriptionEvent(ctx, eventData); if (!eventData.customer) { await this.logHistoryEntry( ctx, diff --git a/packages/vendure-plugin-stripe-subscription/src/stripe-subscription.plugin.ts b/packages/vendure-plugin-stripe-subscription/src/stripe-subscription.plugin.ts index 9a6cbf8d..ae20a41a 100644 --- a/packages/vendure-plugin-stripe-subscription/src/stripe-subscription.plugin.ts +++ b/packages/vendure-plugin-stripe-subscription/src/stripe-subscription.plugin.ts @@ -26,6 +26,7 @@ import { StripeSubscriptionService } from './api/stripe-subscription.service'; import { stripeSubscriptionHandler } from './api/stripe-subscription.handler'; import { hasStripeSubscriptionProductsPaymentChecker } from './api/has-stripe-subscription-products-payment-checker'; import { subscriptionPromotions } from './api/subscription.promotion'; +import { StripeSubscriptionPayment } from './api/stripe-subscription-payment.entity'; export interface StripeSubscriptionPluginOptions { /** @@ -36,7 +37,7 @@ export interface StripeSubscriptionPluginOptions { @VendurePlugin({ imports: [PluginCommonModule], - entities: [Schedule], + entities: [Schedule, StripeSubscriptionPayment], shopApiExtensions: { schema: shopSchemaExtensions, resolvers: [ShopResolver, ShopOrderLinePricingResolver], @@ -85,8 +86,8 @@ export class StripeSubscriptionPlugin { ngModules: [ { type: 'lazy', - route: 'subscription-schedules', - ngModuleFileName: 'schedules.module.ts', + route: 'stripe', + ngModuleFileName: 'stripe-subscription.module.ts', ngModuleName: 'SchedulesModule', }, { diff --git a/packages/vendure-plugin-stripe-subscription/src/ui/payments-component/payments-component.html b/packages/vendure-plugin-stripe-subscription/src/ui/payments-component/payments-component.html new file mode 100644 index 00000000..769dee2a --- /dev/null +++ b/packages/vendure-plugin-stripe-subscription/src/ui/payments-component/payments-component.html @@ -0,0 +1,91 @@ + + + + + {{ payment.id }} + + + + {{ payment.createdAt | localeDate : 'short' }} + + + + + {{ payment.updatedAt | localeDate : 'short' }} + + + + + {{ payment.collectionMethod }} + + + + {{ payment.charge }} + + + {{ payment.currency }} + + + {{ payment.orderCode }} + + + + Channel + + + + + + {{ payment.subscriptionId }} + + diff --git a/packages/vendure-plugin-stripe-subscription/src/ui/payments-component/payments.component.ts b/packages/vendure-plugin-stripe-subscription/src/ui/payments-component/payments.component.ts new file mode 100644 index 00000000..290c01fd --- /dev/null +++ b/packages/vendure-plugin-stripe-subscription/src/ui/payments-component/payments.component.ts @@ -0,0 +1,80 @@ +import { Component, OnInit } from '@angular/core'; +import { TypedBaseListComponent } from '@vendure/admin-ui/core'; +import { StripeSubscriptionPaymentsDocument } from '../generated/graphql'; +import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; +import { + DataService, + ModalService, + NotificationService, +} from '@vendure/admin-ui/core'; +@Component({ + selector: 'payments-component', + templateUrl: './payments-component.html', +}) +export class PaymentsComponent + extends TypedBaseListComponent< + typeof StripeSubscriptionPaymentsDocument, + 'stripeSubscriptionPayments' + > + implements OnInit +{ + readonly filters: any = ( + this.createFilterCollection().addDateFilters() as any + ) + .addFilters([ + { + name: 'id', + type: { kind: 'text' }, + label: _('common.id'), + filterField: 'id', + }, + ]) + .connectToRoute(this.route); + readonly sorts: any = this.createSortCollection() + .defaultSort('createdAt', 'DESC') + .addSorts([ + { name: 'id' }, + { name: 'createdAt' }, + { name: 'updatedAt' }, + { name: 'name' }, + { name: 'collectionMethod' }, + { name: 'charge' }, + { name: 'currency' }, + { name: 'orderCode' }, + { name: 'channelId' }, + { name: 'subscriptionId' }, + ]) + .connectToRoute(this.route); + ngOnInit(): void { + super.ngOnInit(); + } + constructor( + protected dataService: DataService, + private modalService: ModalService, + private notificationService: NotificationService + ) { + super(); + this.configure({ + document: StripeSubscriptionPaymentsDocument, + getItems: (data) => data.stripeSubscriptionPayments, + setVariables: (skip, take) => + ({ + options: { + skip, + take, + filter: { + name: { + contains: this.searchTermControl.value, + }, + ...this.filters.createFilterInput(), + }, + sort: this.sorts.createSortInput() as any, + }, + } as any), + refreshListOnChanges: [ + this.sorts.valueChanges, + this.filters.valueChanges, + ], + }); + } +} diff --git a/packages/vendure-plugin-stripe-subscription/src/ui/queries.ts b/packages/vendure-plugin-stripe-subscription/src/ui/queries.ts index 575a80e5..6bbf84e3 100644 --- a/packages/vendure-plugin-stripe-subscription/src/ui/queries.ts +++ b/packages/vendure-plugin-stripe-subscription/src/ui/queries.ts @@ -19,11 +19,40 @@ export const SCHEDULE_FRAGMENT = gql` } `; +export const PAYMENT_FRAGMENT = gql` + fragment PaymentFields on StripeSubscriptionPayment { + id + createdAt + updatedAt + collectionMethod + charge + currency + orderCode + channelId + subscriptionId + } +`; + export const GET_SCHEDULES = gql` ${SCHEDULE_FRAGMENT} query stripeSubscriptionSchedules { stripeSubscriptionSchedules { - ...ScheduleFields + items { + ...ScheduleFields + } + totalItems + } + } +`; + +export const GET_PAYMENTS = gql` + ${PAYMENT_FRAGMENT} + query stripeSubscriptionPayments { + stripeSubscriptionPayments { + items { + ...PaymentFields + } + totalItems } } `; diff --git a/packages/vendure-plugin-stripe-subscription/src/ui/schedules-component/schedules.component-2.html b/packages/vendure-plugin-stripe-subscription/src/ui/schedules-component/schedules.component-2.html new file mode 100644 index 00000000..205ab590 --- /dev/null +++ b/packages/vendure-plugin-stripe-subscription/src/ui/schedules-component/schedules.component-2.html @@ -0,0 +1,333 @@ + + + +

Stripe Subscription Schedules

+

+ Manage subscription schedules here. A schedule can be connected to a + product variant to make it a subscription. +

+
+ + + +
+
+ + + + + + + {{ schedule.id }} + + + + {{ schedule.createdAt | localeDate : 'short' }} + + + + + {{ schedule.updatedAt | localeDate : 'short' }} + + + + + + {{ schedule.name }} + + + + + + {{ schedule.downpayment | localeCurrency }} + + + + + {{ schedule.durationInterval }} + + + + + {{ schedule.durationCount }} + + + + + {{ schedule.startMoment }} + + + + + {{ schedule.billingInterval }} + + + + + {{ schedule.billingCount }} + + + + + {{ schedule.paidUpFront }} + + + + + {{ schedule.fixedStartDate | localeDate : 'short'}} + + + + + {{ schedule.useProration }} + + + + + {{ schedule.autoRenew }} + + + + + + +
+
+
+ + + + + + + + + + + + + + + + every + + + + + + + + + + of the {{ form.value.isPaidUpFront ? + form.value.durationInterval : form.value.billingInterval + }} + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+
diff --git a/packages/vendure-plugin-stripe-subscription/src/ui/schedules-component/schedules.component-2.ts b/packages/vendure-plugin-stripe-subscription/src/ui/schedules-component/schedules.component-2.ts new file mode 100644 index 00000000..4c32f848 --- /dev/null +++ b/packages/vendure-plugin-stripe-subscription/src/ui/schedules-component/schedules.component-2.ts @@ -0,0 +1,324 @@ +import { ChangeDetectorRef, Component, OnInit } from '@angular/core'; +import { FormBuilder, FormGroup, Validators } from '@angular/forms'; +import { + DataService, + ModalService, + NotificationService, +} from '@vendure/admin-ui/core'; +import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; +import { DELETE_SCHEDULE, GET_SCHEDULES, UPSERT_SCHEDULES } from '../queries'; +import { + StripeSubscriptionSchedule, + StripeSubscriptionSchedulesDocument, + SubscriptionInterval, + SubscriptionStartMoment, +} from '../generated/graphql'; +import { TypedBaseListComponent } from '@vendure/admin-ui/core'; + +@Component({ + selector: 'stripe-subscription-component-2', + styleUrls: ['./schedules.component.scss'], + templateUrl: './schedules.component-2.html', +}) +export class SchedulesComponent + extends TypedBaseListComponent< + typeof StripeSubscriptionSchedulesDocument, + 'stripeSubscriptionSchedules' + > + implements OnInit +{ + readonly filters: any = ( + this.createFilterCollection().addDateFilters() as any + ) + .addFilters([ + { + name: 'id', + type: { kind: 'text' }, + label: _('common.id'), + filterField: 'id', + }, + ]) + .connectToRoute(this.route); + readonly sorts: any = this.createSortCollection() + .defaultSort('createdAt', 'DESC') + .addSorts([ + { name: 'id' }, + { name: 'createdAt' }, + { name: 'updatedAt' }, + { name: 'name' }, + { name: 'downpayment' }, + { name: 'durationInterval' }, + { name: 'durationCount' }, + { name: 'startMoment' }, + { name: 'billingInterval' }, + { name: 'billingCount' }, + { name: 'paidUpFront' }, + { name: 'fixedStartDate' }, + { name: 'useProration' }, + { name: 'autoRenew' }, + ]) + .connectToRoute(this.route); + schedules: StripeSubscriptionSchedule[] = []; + selectedSchedule?: StripeSubscriptionSchedule; + page = 1; + itemsPerPage = 10; + form: FormGroup; + currencyCode!: string; + intervals = [SubscriptionInterval.Week, SubscriptionInterval.Month]; + moments = [ + { + name: 'First', + value: SubscriptionStartMoment.StartOfBillingInterval, + }, + { + name: 'Last', + value: SubscriptionStartMoment.EndOfBillingInterval, + }, + { + name: 'Time of purchase', + value: SubscriptionStartMoment.TimeOfPurchase, + }, + { + name: 'Fixed date', + value: SubscriptionStartMoment.FixedStartdate, + }, + ]; + + constructor( + private formBuilder: FormBuilder, + protected dataService: DataService, + private changeDetector: ChangeDetectorRef, + private notificationService: NotificationService, + private modalService: ModalService + ) { + super(); + this.form = this.formBuilder.group({ + name: ['name', Validators.required], + isPaidUpFront: [false], + downpayment: [0, Validators.required], + durationInterval: ['durationInterval', Validators.required], + durationCount: ['durationCount', Validators.required], + startMoment: ['startMoment', Validators.required], + billingInterval: ['billingInterval', Validators.required], + billingCount: ['billingCount', Validators.required], + fixedStartDate: ['fixedStartDate'], + useProration: [false], + autoRenew: [true], + }); + this.configure({ + document: StripeSubscriptionSchedulesDocument, + getItems: (data) => data.stripeSubscriptionSchedules, + setVariables: (skip, take) => + ({ + options: { + skip, + take, + filter: { + name: { + contains: this.searchTermControl.value, + }, + ...this.filters.createFilterInput(), + }, + sort: this.sorts.createSortInput() as any, + }, + } as any), + refreshListOnChanges: [ + this.sorts.valueChanges, + this.filters.valueChanges, + ], + }); + } + get now() { + return new Date().toISOString(); + } + + closeDetail() { + this.selectedSchedule = undefined; + } + + async ngOnInit(): Promise { + // await this.fetchSchedules(); + super.ngOnInit(); + this.dataService.settings.getActiveChannel().single$.subscribe((data) => { + this.currencyCode = data.activeChannel.defaultCurrencyCode; + }); + } + + selectDurationInterval(interval: 'week' | 'month') { + this.form.controls['durationInterval'].setValue(interval); + } + + selectBillingInterval(interval: 'week' | 'month') { + this.form.controls['billingInterval'].setValue(interval); + } + + edit(scheduleId: string): void { + this.items$.subscribe((schedules) => { + this.selectedSchedule = schedules.find((s) => s.id === scheduleId) as any; + if (!this.selectedSchedule) { + return; + } + this.form.controls['name'].setValue(this.selectedSchedule.name); + this.form.controls['downpayment'].setValue( + this.selectedSchedule.downpayment + ); + this.form.controls['durationInterval'].setValue( + this.selectedSchedule.durationInterval + ); + this.form.controls['durationCount'].setValue( + this.selectedSchedule.durationCount + ); + this.form.controls['startMoment'].setValue( + this.selectedSchedule.startMoment + ); + this.form.controls['billingInterval'].setValue( + this.selectedSchedule.billingInterval + ); + this.form.controls['billingCount'].setValue( + this.selectedSchedule.billingCount + ); + this.form.controls['isPaidUpFront'].setValue( + this.selectedSchedule.paidUpFront + ); + this.form.controls['fixedStartDate'].setValue( + this.selectedSchedule.fixedStartDate + ); + this.form.controls['useProration'].setValue( + this.selectedSchedule.useProration + ); + this.form.controls['autoRenew'].setValue(this.selectedSchedule.autoRenew); + }); + } + + newSchedule(): void { + this.selectedSchedule = { + name: 'New schedule', + downpayment: 0, + durationInterval: SubscriptionInterval.Month, + durationCount: 6, + startMoment: SubscriptionStartMoment.StartOfBillingInterval, + billingInterval: SubscriptionInterval.Month, + billingCount: 1, + } as StripeSubscriptionSchedule; + this.form.controls['name'].setValue(this.selectedSchedule.name); + this.form.controls['downpayment'].setValue( + this.selectedSchedule.downpayment + ); + this.form.controls['durationInterval'].setValue( + this.selectedSchedule.durationInterval + ); + this.form.controls['durationCount'].setValue( + this.selectedSchedule.durationCount + ); + this.form.controls['startMoment'].setValue( + this.selectedSchedule.startMoment + ); + this.form.controls['billingInterval'].setValue( + this.selectedSchedule.billingInterval + ); + this.form.controls['billingCount'].setValue( + this.selectedSchedule.billingCount + ); + this.form.controls['billingCount'].setValue( + this.selectedSchedule.billingCount + ); + this.form.controls['fixedStartDate'].setValue(undefined); + } + + async save(): Promise { + try { + if (this.form.dirty) { + const formValue = this.form.value; + if (formValue.isPaidUpFront) { + formValue.downpayment = 0; + // For paid up front duration and billing cycles are the same + formValue.billingInterval = formValue.durationInterval; + formValue.billingCount = formValue.durationCount; + } + if (formValue.startMoment === SubscriptionStartMoment.FixedStartdate) { + formValue.useProration = false; + } + await this.dataService + .mutate(UPSERT_SCHEDULES, { + input: { + id: this.selectedSchedule?.id, + name: formValue.name, + downpayment: formValue.downpayment, + durationInterval: formValue.durationInterval, + durationCount: formValue.durationCount, + startMoment: formValue.startMoment, + billingInterval: formValue.billingInterval, + billingCount: formValue.billingCount, + fixedStartDate: formValue.fixedStartDate, + useProration: formValue.useProration, + autoRenew: formValue.autoRenew, + }, + }) + .toPromise(); + } + this.form.markAsPristine(); + this.changeDetector.markForCheck(); + this.notificationService.success('common.notify-update-success', { + entity: 'Schedule', + }); + } catch (e) { + this.notificationService.error('common.notify-update-error', { + entity: 'Schedule', + }); + } finally { + super.ngOnInit(); + this.selectedSchedule = undefined; + } + } + + deleteSchedule(scheduleId: string): void { + this.modalService + .dialog({ + title: 'Are you sure you want to delete this schedule?', + buttons: [ + { type: 'secondary', label: 'Cancel' }, + { type: 'danger', label: 'Delete', returnValue: true }, + ], + }) + .subscribe(async (confirm) => { + if (confirm) { + await this.dataService + .mutate(DELETE_SCHEDULE, { scheduleId }) + .toPromise(); + this.notificationService.success('Deleted schedule', { + entity: 'Product', + }); + this.selectedSchedule = undefined; + await this.fetchSchedules(); + } + }); + } + + closeEdit() { + this.selectedSchedule = undefined; + } + + async fetchSchedules(): Promise { + this.dataService + .query(GET_SCHEDULES) + .refetchOnChannelChange() + .mapStream((result: any) => result.stripeSubscriptionSchedules) + .subscribe((schedules) => { + this.schedules = schedules.slice( + (this.page - 1) * this.itemsPerPage, + this.itemsPerPage + ); + }); + } + + async setPageNumber(page: number) { + this.page = page; + await this.fetchSchedules(); + } + + async setItemsPerPage(nrOfItems: number) { + this.page = 1; + this.itemsPerPage = Number(nrOfItems); + await this.fetchSchedules(); + } +} diff --git a/packages/vendure-plugin-stripe-subscription/src/ui/schedules-component/schedules.component.html b/packages/vendure-plugin-stripe-subscription/src/ui/schedules-component/schedules.component.html new file mode 100644 index 00000000..e85a9f92 --- /dev/null +++ b/packages/vendure-plugin-stripe-subscription/src/ui/schedules-component/schedules.component.html @@ -0,0 +1,214 @@ +

Stripe Subscription Schedules

+

+ Manage subscription schedules here. A schedule can be connected to a product + variant to make it a subscription. +

+
+ +
+ + + {{ schedule.id }} + {{ schedule.name }} + + {{ schedule.createdAt | date }} + + + + + + + + + +
+
+
+

+ {{ + selectedSchedule?.id + ? 'Edit schedule ' + selectedSchedule?.id + : 'Create new schedule' + }} +

+ +
+
+ +
+
+ + + + + + + + + + + + + + + + every + + + + + + + + + + of the + {{ + form.value.isPaidUpFront + ? form.value.durationInterval + : form.value.billingInterval + }} + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
diff --git a/packages/vendure-plugin-stripe-subscription/src/ui/schedules.component.scss b/packages/vendure-plugin-stripe-subscription/src/ui/schedules-component/schedules.component.scss similarity index 100% rename from packages/vendure-plugin-stripe-subscription/src/ui/schedules.component.scss rename to packages/vendure-plugin-stripe-subscription/src/ui/schedules-component/schedules.component.scss diff --git a/packages/vendure-plugin-stripe-subscription/src/ui/schedules-component/schedules.component.ts b/packages/vendure-plugin-stripe-subscription/src/ui/schedules-component/schedules.component.ts new file mode 100644 index 00000000..32f48985 --- /dev/null +++ b/packages/vendure-plugin-stripe-subscription/src/ui/schedules-component/schedules.component.ts @@ -0,0 +1,253 @@ +import { ChangeDetectorRef, Component, OnInit } from '@angular/core'; +import { FormBuilder, FormGroup, Validators } from '@angular/forms'; +import { + DataService, + ModalService, + NotificationService, +} from '@vendure/admin-ui/core'; +import { DELETE_SCHEDULE, GET_SCHEDULES, UPSERT_SCHEDULES } from '../queries'; +import { + StripeSubscriptionSchedule, + SubscriptionInterval, + SubscriptionStartMoment, +} from '../generated/graphql'; + +@Component({ + selector: 'stripe-subscription-component', + styleUrls: ['./schedules.component.scss'], + templateUrl: './schedules.component.html', +}) +export class SchedulesComponent implements OnInit { + schedules: StripeSubscriptionSchedule[] = []; + selectedSchedule?: StripeSubscriptionSchedule; + page = 1; + itemsPerPage = 10; + form: FormGroup; + currencyCode!: string; + intervals = [SubscriptionInterval.Week, SubscriptionInterval.Month]; + moments = [ + { + name: 'First', + value: SubscriptionStartMoment.StartOfBillingInterval, + }, + { + name: 'Last', + value: SubscriptionStartMoment.EndOfBillingInterval, + }, + { + name: 'Time of purchase', + value: SubscriptionStartMoment.TimeOfPurchase, + }, + { + name: 'Fixed date', + value: SubscriptionStartMoment.FixedStartdate, + }, + ]; + + constructor( + private formBuilder: FormBuilder, + protected dataService: DataService, + private changeDetector: ChangeDetectorRef, + private notificationService: NotificationService, + private modalService: ModalService + ) { + this.form = this.formBuilder.group({ + name: ['name', Validators.required], + isPaidUpFront: [false], + downpayment: [0, Validators.required], + durationInterval: ['durationInterval', Validators.required], + durationCount: ['durationCount', Validators.required], + startMoment: ['startMoment', Validators.required], + billingInterval: ['billingInterval', Validators.required], + billingCount: ['billingCount', Validators.required], + fixedStartDate: ['fixedStartDate'], + useProration: [false], + autoRenew: [true], + }); + } + get now() { + return new Date().toISOString(); + } + + async ngOnInit(): Promise { + await this.fetchSchedules(); + this.dataService.settings.getActiveChannel().single$.subscribe((data) => { + this.currencyCode = data.activeChannel.defaultCurrencyCode; + }); + } + + selectDurationInterval(interval: 'week' | 'month') { + this.form.controls['durationInterval'].setValue(interval); + } + + selectBillingInterval(interval: 'week' | 'month') { + this.form.controls['billingInterval'].setValue(interval); + } + + edit(scheduleId: string): void { + this.selectedSchedule = this.schedules.find((s) => s.id === scheduleId); + if (!this.selectedSchedule) { + return; + } + this.form.controls['name'].setValue(this.selectedSchedule.name); + this.form.controls['downpayment'].setValue( + this.selectedSchedule.downpayment + ); + this.form.controls['durationInterval'].setValue( + this.selectedSchedule.durationInterval + ); + this.form.controls['durationCount'].setValue( + this.selectedSchedule.durationCount + ); + this.form.controls['startMoment'].setValue( + this.selectedSchedule.startMoment + ); + this.form.controls['billingInterval'].setValue( + this.selectedSchedule.billingInterval + ); + this.form.controls['billingCount'].setValue( + this.selectedSchedule.billingCount + ); + this.form.controls['isPaidUpFront'].setValue( + this.selectedSchedule.paidUpFront + ); + this.form.controls['fixedStartDate'].setValue( + this.selectedSchedule.fixedStartDate + ); + this.form.controls['useProration'].setValue( + this.selectedSchedule.useProration + ); + this.form.controls['autoRenew'].setValue(this.selectedSchedule.autoRenew); + } + + newSchedule(): void { + this.selectedSchedule = { + name: 'New schedule', + downpayment: 0, + durationInterval: SubscriptionInterval.Month, + durationCount: 6, + startMoment: SubscriptionStartMoment.StartOfBillingInterval, + billingInterval: SubscriptionInterval.Month, + billingCount: 1, + } as StripeSubscriptionSchedule; + this.form.controls['name'].setValue(this.selectedSchedule.name); + this.form.controls['downpayment'].setValue( + this.selectedSchedule.downpayment + ); + this.form.controls['durationInterval'].setValue( + this.selectedSchedule.durationInterval + ); + this.form.controls['durationCount'].setValue( + this.selectedSchedule.durationCount + ); + this.form.controls['startMoment'].setValue( + this.selectedSchedule.startMoment + ); + this.form.controls['billingInterval'].setValue( + this.selectedSchedule.billingInterval + ); + this.form.controls['billingCount'].setValue( + this.selectedSchedule.billingCount + ); + this.form.controls['billingCount'].setValue( + this.selectedSchedule.billingCount + ); + this.form.controls['fixedStartDate'].setValue(undefined); + } + + async save(): Promise { + try { + if (this.form.dirty) { + const formValue = this.form.value; + if (formValue.isPaidUpFront) { + formValue.downpayment = 0; + // For paid up front duration and billing cycles are the same + formValue.billingInterval = formValue.durationInterval; + formValue.billingCount = formValue.durationCount; + } + if (formValue.startMoment === SubscriptionStartMoment.FixedStartdate) { + formValue.useProration = false; + } + await this.dataService + .mutate(UPSERT_SCHEDULES, { + input: { + id: this.selectedSchedule?.id, + name: formValue.name, + downpayment: formValue.downpayment, + durationInterval: formValue.durationInterval, + durationCount: formValue.durationCount, + startMoment: formValue.startMoment, + billingInterval: formValue.billingInterval, + billingCount: formValue.billingCount, + fixedStartDate: formValue.fixedStartDate, + useProration: formValue.useProration, + autoRenew: formValue.autoRenew, + }, + }) + .toPromise(); + } + this.form.markAsPristine(); + this.changeDetector.markForCheck(); + this.notificationService.success('common.notify-update-success', { + entity: 'Schedule', + }); + } catch (e) { + this.notificationService.error('common.notify-update-error', { + entity: 'Schedule', + }); + } finally { + await this.fetchSchedules(); + } + } + + deleteSchedule(scheduleId: string): void { + this.modalService + .dialog({ + title: 'Are you sure you want to delete this schedule?', + buttons: [ + { type: 'secondary', label: 'Cancel' }, + { type: 'danger', label: 'Delete', returnValue: true }, + ], + }) + .subscribe(async (confirm) => { + if (confirm) { + await this.dataService + .mutate(DELETE_SCHEDULE, { scheduleId }) + .toPromise(); + this.notificationService.success('Deleted schedule', { + entity: 'Product', + }); + this.selectedSchedule = undefined; + await this.fetchSchedules(); + } + }); + } + + closeEdit() { + this.selectedSchedule = undefined; + } + + async fetchSchedules(): Promise { + this.dataService + .query(GET_SCHEDULES) + .refetchOnChannelChange() + .mapStream((result: any) => result.stripeSubscriptionSchedules) + .subscribe((schedules) => { + this.schedules = schedules.items.slice( + (this.page - 1) * this.itemsPerPage, + this.itemsPerPage + ); + }); + } + + async setPageNumber(page: number) { + this.page = page; + await this.fetchSchedules(); + } + + async setItemsPerPage(nrOfItems: number) { + this.page = 1; + this.itemsPerPage = Number(nrOfItems); + await this.fetchSchedules(); + } +} diff --git a/packages/vendure-plugin-stripe-subscription/src/ui/schedules.component.ts b/packages/vendure-plugin-stripe-subscription/src/ui/schedules.component.ts deleted file mode 100644 index 959a9dfb..00000000 --- a/packages/vendure-plugin-stripe-subscription/src/ui/schedules.component.ts +++ /dev/null @@ -1,476 +0,0 @@ -import { ChangeDetectorRef, Component, OnInit } from '@angular/core'; -import { FormBuilder, FormGroup, Validators } from '@angular/forms'; -import { - DataService, - ModalService, - NotificationService, -} from '@vendure/admin-ui/core'; -import { DELETE_SCHEDULE, GET_SCHEDULES, UPSERT_SCHEDULES } from './queries'; -import { - StripeSubscriptionSchedule, - SubscriptionInterval, - SubscriptionStartMoment, -} from './generated/graphql'; - -@Component({ - selector: 'stripe-subscription-component', - styleUrls: ['./schedules.component.scss'], - template: ` -

Stripe Subscription Schedules

-

- Manage subscription schedules here. A schedule can be connected to a - product variant to make it a subscription. -

-
- -
- - - {{ schedule.id }} - {{ schedule.name }} - - {{ schedule.createdAt | date }} - - - - - - - - - -
-
-
-

- {{ - selectedSchedule?.id - ? 'Edit schedule ' + selectedSchedule?.id - : 'Create new schedule' - }} -

- -
-
- -
-
- - - - - - - - - - - - - - - - every - - - - - - - - - - of the - {{ - form.value.isPaidUpFront - ? form.value.durationInterval - : form.value.billingInterval - }} - - - - - - - - - - - - - - - - - - - - - - - -
-
-
-
- `, -}) -export class SchedulesComponent implements OnInit { - schedules: StripeSubscriptionSchedule[] = []; - selectedSchedule?: StripeSubscriptionSchedule; - page = 1; - itemsPerPage = 10; - form: FormGroup; - currencyCode!: string; - intervals = [SubscriptionInterval.Week, SubscriptionInterval.Month]; - moments = [ - { - name: 'First', - value: SubscriptionStartMoment.StartOfBillingInterval, - }, - { - name: 'Last', - value: SubscriptionStartMoment.EndOfBillingInterval, - }, - { - name: 'Time of purchase', - value: SubscriptionStartMoment.TimeOfPurchase, - }, - { - name: 'Fixed date', - value: SubscriptionStartMoment.FixedStartdate, - }, - ]; - - constructor( - private formBuilder: FormBuilder, - protected dataService: DataService, - private changeDetector: ChangeDetectorRef, - private notificationService: NotificationService, - private modalService: ModalService - ) { - this.form = this.formBuilder.group({ - name: ['name', Validators.required], - isPaidUpFront: [false], - downpayment: [0, Validators.required], - durationInterval: ['durationInterval', Validators.required], - durationCount: ['durationCount', Validators.required], - startMoment: ['startMoment', Validators.required], - billingInterval: ['billingInterval', Validators.required], - billingCount: ['billingCount', Validators.required], - fixedStartDate: ['fixedStartDate'], - useProration: [false], - autoRenew: [true], - }); - } - get now() { - return new Date().toISOString(); - } - - async ngOnInit(): Promise { - await this.fetchSchedules(); - this.dataService.settings.getActiveChannel().single$.subscribe((data) => { - this.currencyCode = data.activeChannel.defaultCurrencyCode; - }); - } - - selectDurationInterval(interval: 'week' | 'month') { - this.form.controls['durationInterval'].setValue(interval); - } - - selectBillingInterval(interval: 'week' | 'month') { - this.form.controls['billingInterval'].setValue(interval); - } - - edit(scheduleId: string): void { - this.selectedSchedule = this.schedules.find((s) => s.id === scheduleId); - if (!this.selectedSchedule) { - return; - } - this.form.controls['name'].setValue(this.selectedSchedule.name); - this.form.controls['downpayment'].setValue( - this.selectedSchedule.downpayment - ); - this.form.controls['durationInterval'].setValue( - this.selectedSchedule.durationInterval - ); - this.form.controls['durationCount'].setValue( - this.selectedSchedule.durationCount - ); - this.form.controls['startMoment'].setValue( - this.selectedSchedule.startMoment - ); - this.form.controls['billingInterval'].setValue( - this.selectedSchedule.billingInterval - ); - this.form.controls['billingCount'].setValue( - this.selectedSchedule.billingCount - ); - this.form.controls['isPaidUpFront'].setValue( - this.selectedSchedule.paidUpFront - ); - this.form.controls['fixedStartDate'].setValue( - this.selectedSchedule.fixedStartDate - ); - this.form.controls['useProration'].setValue( - this.selectedSchedule.useProration - ); - this.form.controls['autoRenew'].setValue(this.selectedSchedule.autoRenew); - } - - newSchedule(): void { - this.selectedSchedule = { - name: 'New schedule', - downpayment: 0, - durationInterval: SubscriptionInterval.Month, - durationCount: 6, - startMoment: SubscriptionStartMoment.StartOfBillingInterval, - billingInterval: SubscriptionInterval.Month, - billingCount: 1, - } as StripeSubscriptionSchedule; - this.form.controls['name'].setValue(this.selectedSchedule.name); - this.form.controls['downpayment'].setValue( - this.selectedSchedule.downpayment - ); - this.form.controls['durationInterval'].setValue( - this.selectedSchedule.durationInterval - ); - this.form.controls['durationCount'].setValue( - this.selectedSchedule.durationCount - ); - this.form.controls['startMoment'].setValue( - this.selectedSchedule.startMoment - ); - this.form.controls['billingInterval'].setValue( - this.selectedSchedule.billingInterval - ); - this.form.controls['billingCount'].setValue( - this.selectedSchedule.billingCount - ); - this.form.controls['billingCount'].setValue( - this.selectedSchedule.billingCount - ); - this.form.controls['fixedStartDate'].setValue(undefined); - } - - async save(): Promise { - try { - if (this.form.dirty) { - const formValue = this.form.value; - if (formValue.isPaidUpFront) { - formValue.downpayment = 0; - // For paid up front duration and billing cycles are the same - formValue.billingInterval = formValue.durationInterval; - formValue.billingCount = formValue.durationCount; - } - if (formValue.startMoment === SubscriptionStartMoment.FixedStartdate) { - formValue.useProration = false; - } - await this.dataService - .mutate(UPSERT_SCHEDULES, { - input: { - id: this.selectedSchedule?.id, - name: formValue.name, - downpayment: formValue.downpayment, - durationInterval: formValue.durationInterval, - durationCount: formValue.durationCount, - startMoment: formValue.startMoment, - billingInterval: formValue.billingInterval, - billingCount: formValue.billingCount, - fixedStartDate: formValue.fixedStartDate, - useProration: formValue.useProration, - autoRenew: formValue.autoRenew, - }, - }) - .toPromise(); - } - this.form.markAsPristine(); - this.changeDetector.markForCheck(); - this.notificationService.success('common.notify-update-success', { - entity: 'Schedule', - }); - } catch (e) { - this.notificationService.error('common.notify-update-error', { - entity: 'Schedule', - }); - } finally { - await this.fetchSchedules(); - } - } - - deleteSchedule(scheduleId: string): void { - this.modalService - .dialog({ - title: 'Are you sure you want to delete this schedule?', - buttons: [ - { type: 'secondary', label: 'Cancel' }, - { type: 'danger', label: 'Delete', returnValue: true }, - ], - }) - .subscribe(async (confirm) => { - if (confirm) { - await this.dataService - .mutate(DELETE_SCHEDULE, { scheduleId }) - .toPromise(); - this.notificationService.success('Deleted schedule', { - entity: 'Product', - }); - this.selectedSchedule = undefined; - await this.fetchSchedules(); - } - }); - } - - closeEdit() { - this.selectedSchedule = undefined; - } - - async fetchSchedules(): Promise { - this.dataService - .query(GET_SCHEDULES) - .refetchOnChannelChange() - .mapStream((result: any) => result.stripeSubscriptionSchedules) - .subscribe((schedules) => { - this.schedules = schedules.slice( - (this.page - 1) * this.itemsPerPage, - this.itemsPerPage - ); - }); - } - - async setPageNumber(page: number) { - this.page = page; - await this.fetchSchedules(); - } - - async setItemsPerPage(nrOfItems: number) { - this.page = 1; - this.itemsPerPage = Number(nrOfItems); - await this.fetchSchedules(); - } -} diff --git a/packages/vendure-plugin-stripe-subscription/src/ui/schedules.module.ts b/packages/vendure-plugin-stripe-subscription/src/ui/schedules.module.ts deleted file mode 100644 index c3be74ad..00000000 --- a/packages/vendure-plugin-stripe-subscription/src/ui/schedules.module.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { NgModule } from '@angular/core'; -import { RouterModule } from '@angular/router'; -import { SharedModule } from '@vendure/admin-ui/core'; -import { SchedulesComponent } from './schedules.component'; - -@NgModule({ - imports: [ - SharedModule, - RouterModule.forChild([ - { - path: '', - pathMatch: 'full', - component: SchedulesComponent, - data: { breadcrumb: 'Subscription schedules' }, - }, - ]), - ], - providers: [], - declarations: [SchedulesComponent], -}) -export class SchedulesModule {} diff --git a/packages/vendure-plugin-stripe-subscription/src/ui/stripe-subscription-shared.module.ts b/packages/vendure-plugin-stripe-subscription/src/ui/stripe-subscription-shared.module.ts index dc78070c..9d2db472 100644 --- a/packages/vendure-plugin-stripe-subscription/src/ui/stripe-subscription-shared.module.ts +++ b/packages/vendure-plugin-stripe-subscription/src/ui/stripe-subscription-shared.module.ts @@ -22,14 +22,24 @@ import { HistoryEntryComponent } from './history-entry.component'; }), addNavMenuItem( { - id: 'stripe-subscription-schedules', - label: 'Subscriptions', - routerLink: ['/extensions/subscription-schedules'], + id: 'subscription-schedules', + label: 'Subscriptions schedules', + routerLink: ['/extensions/stripe/subscription-schedules'], icon: 'calendar', requiresPermission: 'UpdateSettings', }, 'settings' ), + addNavMenuItem( + { + id: 'subscription-payments', + label: 'Subscriptions payments', + routerLink: ['/extensions/stripe/subscription-payments'], + icon: 'dollar', + requiresPermission: 'UpdateSettings', + }, + 'settings' + ), ], }) export class StripeSubscriptionSharedModule {} diff --git a/packages/vendure-plugin-stripe-subscription/src/ui/stripe-subscription.module.ts b/packages/vendure-plugin-stripe-subscription/src/ui/stripe-subscription.module.ts new file mode 100644 index 00000000..bf2e1ffa --- /dev/null +++ b/packages/vendure-plugin-stripe-subscription/src/ui/stripe-subscription.module.ts @@ -0,0 +1,27 @@ +import { NgModule } from '@angular/core'; +import { RouterModule } from '@angular/router'; +import { SharedModule } from '@vendure/admin-ui/core'; +import { SchedulesComponent } from './schedules-component/schedules.component'; +import { PaymentsComponent } from './payments-component/payments.component'; +import { SchedulesComponent as Schedules2Component } from './schedules-component/schedules.component-2'; + +@NgModule({ + imports: [ + SharedModule, + RouterModule.forChild([ + { + path: 'subscription-schedules', + component: Schedules2Component, + data: { breadcrumb: 'Subscription schedules' }, + }, + { + path: 'subscription-payments', + component: PaymentsComponent, + data: { breadcrumb: 'Subscription payments' }, + }, + ]), + ], + providers: [], + declarations: [SchedulesComponent, PaymentsComponent, Schedules2Component], +}) +export class SchedulesModule {} diff --git a/packages/vendure-plugin-stripe-subscription/test/dev-server.ts b/packages/vendure-plugin-stripe-subscription/test/dev-server.ts index 5df1011f..0d5140ac 100644 --- a/packages/vendure-plugin-stripe-subscription/test/dev-server.ts +++ b/packages/vendure-plugin-stripe-subscription/test/dev-server.ts @@ -125,6 +125,7 @@ export let clientSecret = 'test'; billingCount: 6, }, }); + console.log(`1st upsert`); await adminClient.query(UPSERT_SCHEDULES, { input: { name: '3 months, billed monthly, 199 downpayment', @@ -136,6 +137,7 @@ export let clientSecret = 'test'; billingCount: 1, }, }); + console.log(`2nd upsert`); const future = new Date('01-01-2024'); await adminClient.query(UPSERT_SCHEDULES, { input: { diff --git a/packages/vendure-plugin-stripe-subscription/test/helpers.ts b/packages/vendure-plugin-stripe-subscription/test/helpers.ts index 04832241..54522987 100644 --- a/packages/vendure-plugin-stripe-subscription/test/helpers.ts +++ b/packages/vendure-plugin-stripe-subscription/test/helpers.ts @@ -186,17 +186,19 @@ export const CREATE_PAYMENT_LINK = gql` export const GET_SCHEDULES = gql` { stripeSubscriptionSchedules { - id - createdAt - updatedAt - name - downpayment - durationInterval - durationCount - startMoment - paidUpFront - billingInterval - billingCount + items { + id + createdAt + updatedAt + name + downpayment + durationInterval + durationCount + startMoment + paidUpFront + billingInterval + billingCount + } } } `; diff --git a/packages/vendure-plugin-stripe-subscription/test/stripe-subscription.spec.ts b/packages/vendure-plugin-stripe-subscription/test/stripe-subscription.spec.ts index 00ab94db..43e5f852 100644 --- a/packages/vendure-plugin-stripe-subscription/test/stripe-subscription.spec.ts +++ b/packages/vendure-plugin-stripe-subscription/test/stripe-subscription.spec.ts @@ -969,8 +969,8 @@ describe('Stripe Subscription Plugin', function () { await adminClient.asSuperAdmin(); const { stripeSubscriptionSchedules: schedules } = await adminClient.query(GET_SCHEDULES); - expect(schedules[0]).toBeDefined(); - expect(schedules[0].id).toBeDefined(); + expect(schedules.items[0]).toBeDefined(); + expect(schedules.items[0].id).toBeDefined(); }); it('Can delete Schedules', async () => { @@ -991,7 +991,7 @@ describe('Stripe Subscription Plugin', function () { const { stripeSubscriptionSchedules: schedules } = await adminClient.query(GET_SCHEDULES); expect( - schedules.find((s: any) => s.id == toBeDeleted.id) + schedules.items.find((s: any) => s.id == toBeDeleted.id) ).toBeUndefined(); }); diff --git a/packages/vendure-plugin-stripe-subscription/yarn.lock b/packages/vendure-plugin-stripe-subscription/yarn.lock index d2b7509c..5e4b7473 100644 --- a/packages/vendure-plugin-stripe-subscription/yarn.lock +++ b/packages/vendure-plugin-stripe-subscription/yarn.lock @@ -1847,6 +1847,18 @@ lodash "~4.17.0" tslib "~2.4.0" +"@graphql-codegen/plugin-helpers@^5.0.0": + version "5.0.1" + resolved "https://registry.yarnpkg.com/@graphql-codegen/plugin-helpers/-/plugin-helpers-5.0.1.tgz#e2429fcfba3f078d5aa18aa062d46c922bbb0d55" + integrity sha512-6L5sb9D8wptZhnhLLBcheSPU7Tg//DGWgc5tQBWX46KYTOTQHGqDpv50FxAJJOyFVJrveN9otWk9UT9/yfY4ww== + dependencies: + "@graphql-tools/utils" "^10.0.0" + change-case-all "1.0.15" + common-tags "1.8.2" + import-from "4.0.0" + lodash "~4.17.0" + tslib "~2.5.0" + "@graphql-codegen/schema-ast@^2.6.1": version "2.6.1" resolved "https://registry.yarnpkg.com/@graphql-codegen/schema-ast/-/schema-ast-2.6.1.tgz#8ba1b38827c034b51ecd3ce88622c2ae6cd3fe1a" @@ -1856,6 +1868,17 @@ "@graphql-tools/utils" "^9.0.0" tslib "~2.4.0" +"@graphql-codegen/typed-document-node@^5.0.1": + version "5.0.1" + resolved "https://registry.yarnpkg.com/@graphql-codegen/typed-document-node/-/typed-document-node-5.0.1.tgz#ac90cf67c61554f63ec100d6076b47c9f0b18b27" + integrity sha512-VFkhCuJnkgtbbgzoCAwTdJe2G1H6sd3LfCrDqWUrQe53y2ukfSb5Ov1PhAIkCBStKCMQBUY9YgGz9GKR40qQ8g== + dependencies: + "@graphql-codegen/plugin-helpers" "^5.0.0" + "@graphql-codegen/visitor-plugin-common" "4.0.1" + auto-bind "~4.0.0" + change-case-all "1.0.15" + tslib "~2.5.0" + "@graphql-codegen/typescript-operations@^2.3.5": version "2.5.13" resolved "https://registry.yarnpkg.com/@graphql-codegen/typescript-operations/-/typescript-operations-2.5.13.tgz#f286c37f9c023356aacaa983ebd32e9e021a05ca" @@ -1894,6 +1917,22 @@ parse-filepath "^1.0.2" tslib "~2.4.0" +"@graphql-codegen/visitor-plugin-common@4.0.1": + version "4.0.1" + resolved "https://registry.yarnpkg.com/@graphql-codegen/visitor-plugin-common/-/visitor-plugin-common-4.0.1.tgz#64e293728b3c186f6767141e41fcdb310e50d367" + integrity sha512-Bi/1z0nHg4QMsAqAJhds+ForyLtk7A3HQOlkrZNm3xEkY7lcBzPtiOTLBtvziwopBsXUxqeSwVjOOFPLS5Yw1Q== + dependencies: + "@graphql-codegen/plugin-helpers" "^5.0.0" + "@graphql-tools/optimize" "^2.0.0" + "@graphql-tools/relay-operation-optimizer" "^7.0.0" + "@graphql-tools/utils" "^10.0.0" + auto-bind "~4.0.0" + change-case-all "1.0.15" + dependency-graph "^0.11.0" + graphql-tag "^2.11.0" + parse-filepath "^1.0.2" + tslib "~2.5.0" + "@graphql-tools/apollo-engine-loader@^7.3.6": version "7.3.26" resolved "https://registry.yarnpkg.com/@graphql-tools/apollo-engine-loader/-/apollo-engine-loader-7.3.26.tgz#91e54460d5579933e42a2010b8688c3459c245d8" @@ -2116,6 +2155,13 @@ dependencies: tslib "^2.4.0" +"@graphql-tools/optimize@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@graphql-tools/optimize/-/optimize-2.0.0.tgz#7a9779d180824511248a50c5a241eff6e7a2d906" + integrity sha512-nhdT+CRGDZ+bk68ic+Jw1OZ99YCDIKYA5AlVAnBHJvMawSx9YQqQAIj4refNc1/LRieGiuWvhbG3jvPVYho0Dg== + dependencies: + tslib "^2.4.0" + "@graphql-tools/prisma-loader@^7.2.49": version "7.2.72" resolved "https://registry.yarnpkg.com/@graphql-tools/prisma-loader/-/prisma-loader-7.2.72.tgz#6304fc23600458396f3ede713d8e2371df7850e3" @@ -2149,6 +2195,15 @@ "@graphql-tools/utils" "^9.2.1" tslib "^2.4.0" +"@graphql-tools/relay-operation-optimizer@^7.0.0": + version "7.0.0" + resolved "https://registry.yarnpkg.com/@graphql-tools/relay-operation-optimizer/-/relay-operation-optimizer-7.0.0.tgz#24367666af87bc5a81748de5e8e9b3c523fd4207" + integrity sha512-UNlJi5y3JylhVWU4MBpL0Hun4Q7IoJwv9xYtmAz+CgRa066szzY7dcuPfxrA7cIGgG/Q6TVsKsYaiF4OHPs1Fw== + dependencies: + "@ardatan/relay-compiler" "12.0.0" + "@graphql-tools/utils" "^10.0.0" + tslib "^2.4.0" + "@graphql-tools/schema@9.0.16": version "9.0.16" resolved "https://registry.yarnpkg.com/@graphql-tools/schema/-/schema-9.0.16.tgz#7d340d69e6094dc01a2b9e625c7bb4fff89ea521" @@ -2228,6 +2283,15 @@ "@graphql-typed-document-node/core" "^3.1.1" tslib "^2.4.0" +"@graphql-tools/utils@^10.0.0": + version "10.0.4" + resolved "https://registry.yarnpkg.com/@graphql-tools/utils/-/utils-10.0.4.tgz#3104bea54752ae54f1f4a67833d7e3b734400dbe" + integrity sha512-MF+nZgGROSnFgyOYWhrl2PuJMlIBvaCH48vtnlnDQKSeDc2fUfOzUVloBAQvnYmK9JBmHHks4Pxv25Ybg3r45Q== + dependencies: + "@graphql-typed-document-node/core" "^3.1.1" + dset "^3.1.2" + tslib "^2.4.0" + "@graphql-tools/wrap@^9.4.2": version "9.4.2" resolved "https://registry.yarnpkg.com/@graphql-tools/wrap/-/wrap-9.4.2.tgz#30835587c4c73be1780908a7cb077d8013aa2703" @@ -3112,18 +3176,18 @@ dependencies: "@types/node" "*" -"@vendure/admin-ui-plugin@2.0.4": - version "2.0.4" - resolved "https://registry.yarnpkg.com/@vendure/admin-ui-plugin/-/admin-ui-plugin-2.0.4.tgz#7e7c0c3fa76c1e5025105049fba1bb3cdf864904" - integrity sha512-+Ivc4LTM5KGwMrYQcTv2CooSZIOMD/lS53K9D46kAdxTjXP8YI/AMfLq35LRvBXiixZ2SIJRW7Um1Ze7FtbqbQ== +"@vendure/admin-ui-plugin@2.0.5": + version "2.0.5" + resolved "https://registry.yarnpkg.com/@vendure/admin-ui-plugin/-/admin-ui-plugin-2.0.5.tgz#34d33180db3fec330be5ad1f95e74ae897119c85" + integrity sha512-dNbfggTM9C7bzl8ZSQbQiQLL04rXrzqAuWWhB3NSCUUkJF+QLRKCHYEaMVkXe1kzcdEYx83CJg+S0H+ufANofw== dependencies: date-fns "^2.30.0" fs-extra "^10.0.0" -"@vendure/admin-ui@^2.0.4": - version "2.0.4" - resolved "https://registry.yarnpkg.com/@vendure/admin-ui/-/admin-ui-2.0.4.tgz#c74b1d181c87b8daf27e8b580899ade7d1d6601c" - integrity sha512-0TtsOSDSYxkG90gr3zjvGcWYDobh7G4tAZb9RfingALN9mgejGgb8WPGrBca4JIZQQT91vtbTpWKsvRGEP9sow== +"@vendure/admin-ui@^2.0.5": + version "2.0.5" + resolved "https://registry.yarnpkg.com/@vendure/admin-ui/-/admin-ui-2.0.5.tgz#d1e3a3f241410c2cd20548358691d8abe5b4175a" + integrity sha512-UdVJNP2aFuzuFgR4kdon7STlHd9UWUen/w1A8tO1S46J8WuOCn08mNtX82WTcl9bloByMer4CGv99wz46VVtzw== dependencies: "@angular/animations" "^16.0.3" "@angular/cdk" "^16.0.2" @@ -3145,7 +3209,7 @@ "@ng-select/ng-select" "^11.0.0" "@ngx-translate/core" "^14.0.0" "@ngx-translate/http-loader" "^7.0.0" - "@vendure/common" "^2.0.4" + "@vendure/common" "^2.0.5" "@webcomponents/custom-elements" "^1.5.1" apollo-angular "^5.0.0" apollo-upload-client "^17.0.0" @@ -3173,15 +3237,15 @@ tslib "^2.5.0" zone.js "~0.13.0" -"@vendure/common@^2.0.4": - version "2.0.4" - resolved "https://registry.yarnpkg.com/@vendure/common/-/common-2.0.4.tgz#60c3972ecedca920afb4867ccf6ba085358caabb" - integrity sha512-G77FlfKxbwX+CNyh2L4q3OrtY3r9riAsVCTEvWzrqNONxQazHsl01tyzWQYE1u/npYKmozEUU8VneejvE9/zyA== +"@vendure/common@^2.0.5": + version "2.0.5" + resolved "https://registry.yarnpkg.com/@vendure/common/-/common-2.0.5.tgz#99e3135d41a698865a1eecbf80e2c70b0f6b1794" + integrity sha512-S4kYKNwJM9DL5TlNZe9aJ3EiK5YPj6zXUqj0ebsQ+HJRHHarO8OK2oj964WprZNwCJDMbZItPzPTIPutnb915g== -"@vendure/core@2.0.4": - version "2.0.4" - resolved "https://registry.yarnpkg.com/@vendure/core/-/core-2.0.4.tgz#51b81105ef547c7a13397f03df3fdde16c9d76ff" - integrity sha512-EZ2lxJgCRLNBWIZ/XpC+516RaB2O40xt7IOAOg4++77iiuM+US1aX7Wi6Nvpsbrs51mA5ZRs3iFBWEnvyuL5NQ== +"@vendure/core@2.0.5": + version "2.0.5" + resolved "https://registry.yarnpkg.com/@vendure/core/-/core-2.0.5.tgz#93099280e98fabd03b466b142d6c296ceb81f0a5" + integrity sha512-+IG+s2GRkfkxlEGR7UEbuuEwjRZMqOCJxvSd6NscUwqel39SIUnVSeETLEpg2tpVM5bRYKdDDIQXNQ7oDHwNOg== dependencies: "@graphql-tools/stitch" "^8.7.43" "@nestjs/apollo" "^10.2.0" @@ -3193,7 +3257,7 @@ "@nestjs/testing" "9.3.9" "@nestjs/typeorm" "9.0.1" "@types/fs-extra" "^9.0.1" - "@vendure/common" "^2.0.4" + "@vendure/common" "^2.0.5" apollo-server-express "3.6.3" bcrypt "^5.1.0" body-parser "^1.19.0" @@ -3223,14 +3287,14 @@ rxjs "^7.5.4" typeorm "0.3.11" -"@vendure/testing@2.0.4": - version "2.0.4" - resolved "https://registry.yarnpkg.com/@vendure/testing/-/testing-2.0.4.tgz#1bdd5eedc60f6d9838c4e0656f17cc1dfb17ec8c" - integrity sha512-PW0PiMwgLBOy7kaFnV1NrCPkMCwefBdIZKwnf9fvaXso0KUreZqKpjRYh7dCYhw1dAfUObPzoHcdp+hRsnqetg== +"@vendure/testing@2.0.5": + version "2.0.5" + resolved "https://registry.yarnpkg.com/@vendure/testing/-/testing-2.0.5.tgz#de15aebc799d224d3dd90d2de71a55b00e3d9d16" + integrity sha512-PyHAKGZ1bUWB8TkiF49mTcrPMOtP7oUOWWm+jeBLlCffxs1KCZTB5nAURufl5xmhTKdThSF6OOP45CuQY7OaPg== dependencies: "@graphql-typed-document-node/core" "^3.2.0" "@types/node-fetch" "^2.5.4" - "@vendure/common" "^2.0.4" + "@vendure/common" "^2.0.5" faker "^4.1.0" form-data "^3.0.0" graphql "16.6.0" @@ -3238,17 +3302,17 @@ node-fetch "^2.6.0" sql.js "1.8.0" -"@vendure/ui-devkit@2.0.4": - version "2.0.4" - resolved "https://registry.yarnpkg.com/@vendure/ui-devkit/-/ui-devkit-2.0.4.tgz#37a5cd45c8e845aea1d4a89a56d67fdb5049778d" - integrity sha512-sFpWHDqD47t7LlMW9zCtoqYXwvG0jJ5c0lxrvBiPl+veF404pYWd6hBGCB7x03cWPrk+YEDsw8r5SHrb/8pcIw== +"@vendure/ui-devkit@2.0.5": + version "2.0.5" + resolved "https://registry.yarnpkg.com/@vendure/ui-devkit/-/ui-devkit-2.0.5.tgz#23e22891d3aa2c45ecc3487876dfe4173f9d4776" + integrity sha512-++jjou5QKwup6sOYG48jlDoqr++JudUnZNIfB5x+KjNnMGx+1o9QhV7CTMfA5f/y9RGiYYW4LmpMUAdTTKhAuA== dependencies: "@angular-devkit/build-angular" "^16.0.3" "@angular/cli" "^16.0.3" "@angular/compiler" "^16.0.3" "@angular/compiler-cli" "^16.0.3" - "@vendure/admin-ui" "^2.0.4" - "@vendure/common" "^2.0.4" + "@vendure/admin-ui" "^2.0.5" + "@vendure/common" "^2.0.5" chalk "^4.1.0" chokidar "^3.5.1" fs-extra "^10.0.0" @@ -9198,7 +9262,7 @@ tslib@2.5.0: resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.5.0.tgz#42bfed86f5787aeb41d031866c8f402429e0fddf" integrity sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg== -tslib@2.5.3: +tslib@2.5.3, tslib@~2.5.0: version "2.5.3" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.5.3.tgz#24944ba2d990940e6e982c4bea147aba80209913" integrity sha512-mSxlJJwl3BMEQCUNnxXBU9jP4JBktcEGhURcPR6VQVlnP0FdDEsIaz0C35dXNGLyRfrATNofF0F5p2KPxQgB+w== From 063a36d41cd4f93ea64b3a8b91250e3f2b0974a0 Mon Sep 17 00:00:00 2001 From: Surafel Melese Date: Wed, 9 Aug 2023 13:04:49 +0300 Subject: [PATCH 02/11] feat: remvoved console logs --- packages/vendure-plugin-stripe-subscription/test/dev-server.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/vendure-plugin-stripe-subscription/test/dev-server.ts b/packages/vendure-plugin-stripe-subscription/test/dev-server.ts index 0d5140ac..5df1011f 100644 --- a/packages/vendure-plugin-stripe-subscription/test/dev-server.ts +++ b/packages/vendure-plugin-stripe-subscription/test/dev-server.ts @@ -125,7 +125,6 @@ export let clientSecret = 'test'; billingCount: 6, }, }); - console.log(`1st upsert`); await adminClient.query(UPSERT_SCHEDULES, { input: { name: '3 months, billed monthly, 199 downpayment', @@ -137,7 +136,6 @@ export let clientSecret = 'test'; billingCount: 1, }, }); - console.log(`2nd upsert`); const future = new Date('01-01-2024'); await adminClient.query(UPSERT_SCHEDULES, { input: { From 9e5b9af1e79f99b465ae2862a982e5cfea4a49db Mon Sep 17 00:00:00 2001 From: Martijn Date: Wed, 9 Aug 2023 15:12:29 +0200 Subject: [PATCH 03/11] feat(stripe-subscription): small updates after live testing --- .../src/api/metrics/average-order-value.ts | 44 ++++ .../src/api/graphql-schemas.ts | 2 +- .../api/stripe-subscription-payment.entity.ts | 5 +- .../src/api/stripe-subscription.controller.ts | 42 ++-- .../src/api/stripe-subscription.service.ts | 62 +++--- .../src/api/types/stripe-invoice.ts | 200 ++++++++++++++++++ .../src/api/types/stripe-payment-intent.ts | 186 ++++++++++++++++ .../src/api/{ => types}/stripe.types.ts | 22 +- .../src/index.ts | 2 +- .../ui/stripe-subscription-shared.module.ts | 4 +- .../test/dev-server.ts | 2 +- 11 files changed, 502 insertions(+), 69 deletions(-) create mode 100644 packages/vendure-plugin-metrics/src/api/metrics/average-order-value.ts create mode 100644 packages/vendure-plugin-stripe-subscription/src/api/types/stripe-invoice.ts create mode 100644 packages/vendure-plugin-stripe-subscription/src/api/types/stripe-payment-intent.ts rename packages/vendure-plugin-stripe-subscription/src/api/{ => types}/stripe.types.ts (60%) diff --git a/packages/vendure-plugin-metrics/src/api/metrics/average-order-value.ts b/packages/vendure-plugin-metrics/src/api/metrics/average-order-value.ts new file mode 100644 index 00000000..0d05b858 --- /dev/null +++ b/packages/vendure-plugin-metrics/src/api/metrics/average-order-value.ts @@ -0,0 +1,44 @@ +import { Injector, Order, RequestContext } from '@vendure/core'; +import { + AdvancedMetricSummaryInput, + AdvancedMetricType, +} from '../../ui/generated/graphql'; +import { MetricStrategy } from '../metric-strategy'; + +/** + * Calculates the average order value per month + */ +export class AverageOrderValueMetric implements MetricStrategy { + readonly metricType: AdvancedMetricType = AdvancedMetricType.Currency; + readonly code = 'aov'; + + getTitle(ctx: RequestContext): string { + return `Average order value in ${ctx.channel.defaultCurrencyCode}`; + } + + sortByDateField(): string { + return 'orderPlacedAt'; + } + + loadData( + ctx: RequestContext, + injector: Injector, + from: Date, + to: Date, + input: AdvancedMetricSummaryInput + ): Promise { + throw new Error('Method not implemented.'); + } + + calculateDataPoint( + ctx: RequestContext, + data: Order[], + monthNr: number + ): number[] { + const total = data + .map((o) => o.totalWithTax) + .reduce((total, current) => total + current); + const average = Math.round(total / data.length) / 100; + return [average]; + } +} diff --git a/packages/vendure-plugin-stripe-subscription/src/api/graphql-schemas.ts b/packages/vendure-plugin-stripe-subscription/src/api/graphql-schemas.ts index d843b9d4..ee54615b 100644 --- a/packages/vendure-plugin-stripe-subscription/src/api/graphql-schemas.ts +++ b/packages/vendure-plugin-stripe-subscription/src/api/graphql-schemas.ts @@ -57,7 +57,7 @@ const sharedTypes = gql` createdAt: DateTime updatedAt: DateTime collectionMethod: String - charge: String + charge: Int currency: String orderCode: String channelId: ID diff --git a/packages/vendure-plugin-stripe-subscription/src/api/stripe-subscription-payment.entity.ts b/packages/vendure-plugin-stripe-subscription/src/api/stripe-subscription-payment.entity.ts index 30a043e3..7fc487d9 100644 --- a/packages/vendure-plugin-stripe-subscription/src/api/stripe-subscription-payment.entity.ts +++ b/packages/vendure-plugin-stripe-subscription/src/api/stripe-subscription-payment.entity.ts @@ -15,7 +15,10 @@ export class StripeSubscriptionPayment extends VendureEntity { collectionMethod!: string; @Column({ nullable: true }) - charge!: string; + eventType!: string; + + @Column({ nullable: true }) + charge!: number; @Column({ nullable: true }) currency!: string; diff --git a/packages/vendure-plugin-stripe-subscription/src/api/stripe-subscription.controller.ts b/packages/vendure-plugin-stripe-subscription/src/api/stripe-subscription.controller.ts index b0f25e31..e05c237e 100644 --- a/packages/vendure-plugin-stripe-subscription/src/api/stripe-subscription.controller.ts +++ b/packages/vendure-plugin-stripe-subscription/src/api/stripe-subscription.controller.ts @@ -11,10 +11,8 @@ import { Allow, Ctx, ID, - ListQueryOptions, Logger, OrderService, - PaginatedList, Permission, ProductService, RequestContext, @@ -24,7 +22,6 @@ import { Request } from 'express'; import { loggerCtx, PLUGIN_INIT_OPTIONS } from '../constants'; import { StripeSubscriptionPluginOptions } from '../stripe-subscription.plugin'; import { - QueryStripeSubscriptionPaymentsArgs, StripeSubscriptionPaymentList, StripeSubscriptionPaymentListOptions, StripeSubscriptionPricing, @@ -36,12 +33,13 @@ import { } from '../ui/generated/graphql'; import { ScheduleService } from './schedule.service'; import { StripeSubscriptionService } from './stripe-subscription.service'; -import { IncomingStripeWebhook } from './stripe.types'; import { OrderLineWithSubscriptionFields, VariantWithSubscriptionFields, } from './subscription-custom-fields'; -import { StripeSubscriptionPayment } from './stripe-subscription-payment.entity'; +import { StripeInvoice } from './types/stripe-invoice'; +import { StripePaymentIntent } from './types/stripe-payment-intent'; +import { IncomingStripeWebhook } from './types/stripe.types'; export type RequestWithRawBody = Request & { rawBody: any }; @@ -187,11 +185,11 @@ export class StripeSubscriptionController { Logger.info(`Incoming webhook ${body.type}`, loggerCtx); // Validate if metadata present const orderCode = - body.data.object.metadata?.orderCode || - body.data.object.lines?.data[0]?.metadata.orderCode; + body.data.object.metadata?.orderCode ?? + (body.data.object as StripeInvoice).lines?.data[0]?.metadata.orderCode; const channelToken = - body.data.object.metadata?.channelToken || - body.data.object.lines?.data[0]?.metadata.channelToken; + body.data.object.metadata?.channelToken ?? + (body.data.object as StripeInvoice).lines?.data[0]?.metadata.channelToken; if ( body.type !== 'payment_intent.succeeded' && body.type !== 'invoice.payment_failed' && @@ -233,27 +231,45 @@ export class StripeSubscriptionController { if (body.type === 'payment_intent.succeeded') { await this.stripeSubscriptionService.handlePaymentIntentSucceeded( ctx, - body, + body.data.object as StripePaymentIntent, order ); } else if (body.type === 'invoice.payment_succeeded') { + const invoiceObject = body.data.object as StripeInvoice; await this.stripeSubscriptionService.handleInvoicePaymentSucceeded( ctx, - body, + invoiceObject, order ); + await this.stripeSubscriptionService.savePaymentEvent( + ctx, + body.type, + invoiceObject + ); } else if (body.type === 'invoice.payment_failed') { + const invoiceObject = body.data.object as StripeInvoice; await this.stripeSubscriptionService.handleInvoicePaymentFailed( ctx, - body, + invoiceObject, order ); + await this.stripeSubscriptionService.savePaymentEvent( + ctx, + body.type, + invoiceObject + ); } else if (body.type === 'invoice.payment_action_required') { + const invoiceObject = body.data.object as StripeInvoice; await this.stripeSubscriptionService.handleInvoicePaymentFailed( ctx, - body, + invoiceObject, order ); + await this.stripeSubscriptionService.savePaymentEvent( + ctx, + body.type, + invoiceObject + ); } Logger.info(`Successfully handled webhook ${body.type}`, loggerCtx); } catch (error) { diff --git a/packages/vendure-plugin-stripe-subscription/src/api/stripe-subscription.service.ts b/packages/vendure-plugin-stripe-subscription/src/api/stripe-subscription.service.ts index 99bb3a74..636ba4e8 100644 --- a/packages/vendure-plugin-stripe-subscription/src/api/stripe-subscription.service.ts +++ b/packages/vendure-plugin-stripe-subscription/src/api/stripe-subscription.service.ts @@ -32,7 +32,7 @@ import { UserInputError, } from '@vendure/core'; import { loggerCtx } from '../constants'; -import { IncomingStripeWebhook } from './stripe.types'; +import { IncomingStripeWebhook } from './types/stripe.types'; import { CustomerWithSubscriptionFields, OrderLineWithSubscriptionFields, @@ -60,6 +60,8 @@ import { Release } from '@vendure/core/dist/entity/stock-movement/release.entity import { randomUUID } from 'crypto'; import { hasSubscriptions } from './has-stripe-subscription-products-payment-checker'; import { StripeSubscriptionPayment } from './stripe-subscription-payment.entity'; +import { StripeInvoice } from './types/stripe-invoice'; +import { StripePaymentIntent } from './types/stripe-payment-intent'; export interface StripeHandlerConfig { paymentMethodCode: string; @@ -401,33 +403,32 @@ export class StripeSubscriptionService { }; } - async saveStripeSubscriptionEvent( + async savePaymentEvent( ctx: RequestContext, - object: any + eventType: string, + object: StripeInvoice ): Promise { const stripeSubscriptionPaymentRepo = this.connection.getRepository( ctx, StripeSubscriptionPayment ); - const channelRepo = this.connection.getRepository(ctx, Channel); - const channelToken = - object.metadata?.channelToken || - object.lines?.data[0]?.metadata.channelToken; - const requestChannel = await channelRepo.findOne({ - where: { token: channelToken }, + const charge = object.lines.data.reduce( + (acc, line) => acc + line.plan.amount, + 0 + ); + const newPayment = new StripeSubscriptionPayment({ + channelId: ctx.channel.id as string, + eventType, + charge: charge, + currency: object.currency ?? ctx.channel.defaultCurrencyCode, + collectionMethod: object.collection_method, + invoiceId: object.id, + orderCode: + object.metadata?.orderCode ?? + object.lines?.data[0]?.metadata.orderCode ?? + '', + subscriptionId: object.subscription, }); - if (!requestChannel) { - throw new InternalServerError(`Channel with ${channelToken} not found`); - } - const newPayment = new StripeSubscriptionPayment(); - newPayment.channelId = requestChannel.id as string; - newPayment.charge = object?.charge; - newPayment.currency = object.currency || requestChannel.defaultCurrencyCode; - newPayment.collectionMethod = object.collection_method; - newPayment.invoiceId = object.id; - newPayment.orderCode = - object.metadata?.orderCode || object.lines?.data[0]?.metadata.orderCode; - newPayment.subscriptionId = object.subscription; await stripeSubscriptionPaymentRepo.save(newPayment); } @@ -449,7 +450,7 @@ export class StripeSubscriptionService { */ async handleInvoicePaymentSucceeded( ctx: RequestContext, - { data: { object } }: IncomingStripeWebhook, + object: StripeInvoice, order: Order ): Promise { const amount = object.lines?.data?.[0]?.plan?.amount; @@ -464,7 +465,6 @@ export class StripeSubscriptionService { undefined, object.subscription ); - await this.saveStripeSubscriptionEvent(ctx, object); } /** @@ -472,7 +472,7 @@ export class StripeSubscriptionService { */ async handleInvoicePaymentFailed( ctx: RequestContext, - { data: { object } }: IncomingStripeWebhook, + object: StripeInvoice, order: Order ): Promise { const amount = object.lines?.data[0]?.plan?.amount; @@ -487,7 +487,6 @@ export class StripeSubscriptionService { undefined, object.subscription ); - await this.saveStripeSubscriptionEvent(ctx, object); } /** @@ -496,12 +495,11 @@ export class StripeSubscriptionService { */ async handlePaymentIntentSucceeded( ctx: RequestContext, - { data: { object: eventData } }: IncomingStripeWebhook, + object: StripePaymentIntent, order: Order ): Promise { const { paymentMethodCode } = await this.getStripeHandler(ctx, order.id); - await this.saveStripeSubscriptionEvent(ctx, eventData); - if (!eventData.customer) { + if (!object.customer) { await this.logHistoryEntry( ctx, order.id, @@ -517,8 +515,8 @@ export class StripeSubscriptionService { action: 'createSubscriptionsForOrder', ctx: ctx.serialize(), orderCode: order.code, - stripePaymentMethodId: eventData.payment_method, - stripeCustomerId: eventData.customer, + stripePaymentMethodId: object.payment_method, + stripeCustomerId: object.customer, }, { retries: 0 } // Only 1 try, because subscription creation isn't transaction-proof ) @@ -547,8 +545,8 @@ export class StripeSubscriptionService { { method: paymentMethodCode, metadata: { - setupIntentId: eventData.id, - amount: eventData.metadata.amount, + setupIntentId: object.id, + amount: object.metadata.amount, }, } ); diff --git a/packages/vendure-plugin-stripe-subscription/src/api/types/stripe-invoice.ts b/packages/vendure-plugin-stripe-subscription/src/api/types/stripe-invoice.ts new file mode 100644 index 00000000..92349250 --- /dev/null +++ b/packages/vendure-plugin-stripe-subscription/src/api/types/stripe-invoice.ts @@ -0,0 +1,200 @@ +import { Metadata } from './stripe.types'; + +export interface StripeInvoice { + id: string; + object: string; + account_country: string; + account_name: string; + account_tax_ids: any; + amount_due: number; + amount_paid: number; + amount_remaining: number; + amount_shipping: number; + application: any; + application_fee_amount: any; + attempt_count: number; + attempted: boolean; + auto_advance: boolean; + automatic_tax: AutomaticTax; + billing_reason: string; + charge: any; + collection_method: string; + created: number; + currency: string; + custom_fields: any; + customer: string; + customer_address: any; + customer_email: string; + customer_name: string; + customer_phone: any; + customer_shipping: any; + customer_tax_exempt: string; + customer_tax_ids: any[]; + default_payment_method: any; + default_source: any; + default_tax_rates: any[]; + description: string; + discount: any; + discounts: any[]; + due_date: any; + effective_at: number; + ending_balance: number; + footer: any; + from_invoice: any; + hosted_invoice_url: string; + invoice_pdf: string; + last_finalization_error: any; + latest_revision: any; + lines: Lines; + livemode: boolean; + metadata: Metadata; + next_payment_attempt: any; + number: string; + on_behalf_of: any; + paid: boolean; + paid_out_of_band: boolean; + payment_intent: any; + payment_settings: PaymentSettings; + period_end: number; + period_start: number; + post_payment_credit_notes_amount: number; + pre_payment_credit_notes_amount: number; + quote: any; + receipt_number: any; + rendering_options: any; + shipping_cost: any; + shipping_details: any; + starting_balance: number; + statement_descriptor: any; + status: string; + status_transitions: StatusTransitions; + subscription: string; + subscription_details: SubscriptionDetails; + subtotal: number; + subtotal_excluding_tax: number; + tax: any; + test_clock: any; + total: number; + total_discount_amounts: any[]; + total_excluding_tax: number; + total_tax_amounts: any[]; + transfer_data: any; + webhooks_delivered_at: number; +} + +export interface AutomaticTax { + enabled: boolean; + status: any; +} + +export interface Lines { + object: string; + data: Daum[]; + has_more: boolean; + total_count: number; + url: string; +} + +export interface Daum { + id: string; + object: string; + amount: number; + amount_excluding_tax: number; + currency: string; + description: string; + discount_amounts: any[]; + discountable: boolean; + discounts: any[]; + livemode: boolean; + metadata: Metadata; + period: Period; + plan: Plan; + price: Price; + proration: boolean; + proration_details: ProrationDetails; + quantity: number; + subscription: string; + subscription_item: string; + tax_amounts: any[]; + tax_rates: any[]; + type: string; + unit_amount_excluding_tax: string; +} + +export interface Period { + end: number; + start: number; +} + +export interface Plan { + id: string; + object: string; + active: boolean; + aggregate_usage: any; + amount: number; + amount_decimal: string; + billing_scheme: string; + created: number; + currency: string; + interval: string; + interval_count: number; + livemode: boolean; + metadata: Metadata; + nickname: any; + product: string; + tiers_mode: any; + transform_usage: any; + trial_period_days: any; + usage_type: string; +} + +export interface Price { + id: string; + object: string; + active: boolean; + billing_scheme: string; + created: number; + currency: string; + custom_unit_amount: any; + livemode: boolean; + lookup_key: any; + metadata: Metadata; + nickname: any; + product: string; + recurring: Recurring; + tax_behavior: string; + tiers_mode: any; + transform_quantity: any; + type: string; + unit_amount: number; + unit_amount_decimal: string; +} + +export interface Recurring { + aggregate_usage: any; + interval: string; + interval_count: number; + trial_period_days: any; + usage_type: string; +} + +export interface ProrationDetails { + credited_items: any; +} + +export interface PaymentSettings { + default_mandate: any; + payment_method_options: any; + payment_method_types: any; +} + +export interface StatusTransitions { + finalized_at: number; + marked_uncollectible_at: any; + paid_at: number; + voided_at: any; +} + +export interface SubscriptionDetails { + metadata: Metadata; +} diff --git a/packages/vendure-plugin-stripe-subscription/src/api/types/stripe-payment-intent.ts b/packages/vendure-plugin-stripe-subscription/src/api/types/stripe-payment-intent.ts new file mode 100644 index 00000000..9d2722a0 --- /dev/null +++ b/packages/vendure-plugin-stripe-subscription/src/api/types/stripe-payment-intent.ts @@ -0,0 +1,186 @@ +import { Metadata } from './stripe.types'; + +export interface StripePaymentIntent { + id: string; + object: string; + amount: number; + amount_capturable: number; + amount_details: AmountDetails; + amount_received: number; + application: any; + application_fee_amount: any; + automatic_payment_methods: any; + canceled_at: any; + cancellation_reason: any; + capture_method: string; + charges: Charges; + client_secret: string; + confirmation_method: string; + created: number; + currency: string; + customer: string; + description: any; + invoice: any; + last_payment_error: any; + latest_charge: string; + livemode: boolean; + metadata: Metadata; + next_action: any; + on_behalf_of: any; + payment_method: string; + payment_method_options: PaymentMethodOptions; + payment_method_types: string[]; + processing: any; + receipt_email: string; + review: any; + setup_future_usage: string; + shipping: any; + source: any; + statement_descriptor: any; + statement_descriptor_suffix: any; + status: string; + transfer_data: any; + transfer_group: any; +} + +export interface AmountDetails { + tip: Tip; +} + +export interface Tip {} + +export interface Charges { + object: string; + data: Daum[]; + has_more: boolean; + total_count: number; + url: string; +} + +export interface Daum { + id: string; + object: string; + amount: number; + amount_captured: number; + amount_refunded: number; + application: any; + application_fee: any; + application_fee_amount: any; + balance_transaction: string; + billing_details: BillingDetails; + calculated_statement_descriptor: string; + captured: boolean; + created: number; + currency: string; + customer: string; + description: any; + destination: any; + dispute: any; + disputed: boolean; + failure_balance_transaction: any; + failure_code: any; + failure_message: any; + fraud_details: FraudDetails; + invoice: any; + livemode: boolean; + metadata: Metadata; + on_behalf_of: any; + order: any; + outcome: Outcome; + paid: boolean; + payment_intent: string; + payment_method: string; + payment_method_details: PaymentMethodDetails; + receipt_email: string; + receipt_number: any; + receipt_url: string; + refunded: boolean; + refunds: Refunds; + review: any; + shipping: any; + source: any; + source_transfer: any; + statement_descriptor: any; + statement_descriptor_suffix: any; + status: string; + transfer_data: any; + transfer_group: any; +} + +export interface BillingDetails { + address: Address; + email: any; + name: any; + phone: any; +} + +export interface Address { + city: any; + country: string; + line1: any; + line2: any; + postal_code: any; + state: any; +} + +export interface FraudDetails {} + +export interface Outcome { + network_status: string; + reason: any; + risk_level: string; + risk_score: number; + seller_message: string; + type: string; +} + +export interface PaymentMethodDetails { + card: Card; + type: string; +} + +export interface Card { + brand: string; + checks: Checks; + country: string; + exp_month: number; + exp_year: number; + fingerprint: string; + funding: string; + installments: any; + last4: string; + mandate: any; + network: string; + network_token: NetworkToken; + three_d_secure: any; + wallet: any; +} + +export interface Checks { + address_line1_check: any; + address_postal_code_check: any; + cvc_check: string; +} + +export interface NetworkToken { + used: boolean; +} + +export interface Refunds { + object: string; + data: any[]; + has_more: boolean; + total_count: number; + url: string; +} + +export interface PaymentMethodOptions { + card: Card2; +} + +export interface Card2 { + installments: any; + mandate_options: any; + network: any; + request_three_d_secure: string; +} diff --git a/packages/vendure-plugin-stripe-subscription/src/api/stripe.types.ts b/packages/vendure-plugin-stripe-subscription/src/api/types/stripe.types.ts similarity index 60% rename from packages/vendure-plugin-stripe-subscription/src/api/stripe.types.ts rename to packages/vendure-plugin-stripe-subscription/src/api/types/stripe.types.ts index cbd42ccf..1555efa5 100644 --- a/packages/vendure-plugin-stripe-subscription/src/api/stripe.types.ts +++ b/packages/vendure-plugin-stripe-subscription/src/api/types/stripe.types.ts @@ -1,3 +1,6 @@ +import { StripeInvoice } from './stripe-invoice'; +import { StripePaymentIntent } from './stripe-payment-intent'; + export interface Metadata { orderCode: string; channelToken: string; @@ -5,25 +8,8 @@ export interface Metadata { amount: number; } -export interface Object { - id: string; - object: string; - customer: string; - payment_method: string; - metadata: Metadata; - subscription: string; - lines?: { - data: { - metadata: Metadata; - plan: { - amount: number; - }; - }[]; - }; -} - export interface Data { - object: Object; + object: StripeInvoice | StripePaymentIntent; } export interface Request { diff --git a/packages/vendure-plugin-stripe-subscription/src/index.ts b/packages/vendure-plugin-stripe-subscription/src/index.ts index c8860e60..d575e490 100644 --- a/packages/vendure-plugin-stripe-subscription/src/index.ts +++ b/packages/vendure-plugin-stripe-subscription/src/index.ts @@ -5,7 +5,7 @@ export * from './api/stripe.client'; export * from './stripe-subscription.plugin'; export * from './api/stripe-subscription.handler'; export * from './api/stripe-subscription.service'; -export * from './api/stripe.types'; +export * from './api/types/stripe.types'; export * from './api/stripe-subscription.controller'; export * from './api/schedule.entity'; export * from './api/subscription.promotion'; diff --git a/packages/vendure-plugin-stripe-subscription/src/ui/stripe-subscription-shared.module.ts b/packages/vendure-plugin-stripe-subscription/src/ui/stripe-subscription-shared.module.ts index 9d2db472..2bddccd8 100644 --- a/packages/vendure-plugin-stripe-subscription/src/ui/stripe-subscription-shared.module.ts +++ b/packages/vendure-plugin-stripe-subscription/src/ui/stripe-subscription-shared.module.ts @@ -36,9 +36,9 @@ import { HistoryEntryComponent } from './history-entry.component'; label: 'Subscriptions payments', routerLink: ['/extensions/stripe/subscription-payments'], icon: 'dollar', - requiresPermission: 'UpdateSettings', + requiresPermission: 'ReadOrder', }, - 'settings' + 'sales' ), ], }) diff --git a/packages/vendure-plugin-stripe-subscription/test/dev-server.ts b/packages/vendure-plugin-stripe-subscription/test/dev-server.ts index 5df1011f..5e059cfb 100644 --- a/packages/vendure-plugin-stripe-subscription/test/dev-server.ts +++ b/packages/vendure-plugin-stripe-subscription/test/dev-server.ts @@ -194,7 +194,7 @@ export let clientSecret = 'test'; }, }); */ let { addItemToOrder: order } = await shopClient.query(ADD_ITEM_TO_ORDER, { - productVariantId: '3', + productVariantId: '2', quantity: 1, customFields: { // downpayment: 40000, From bec22a00d9d488a3c3d2f7ba2e0a52d21d03686d Mon Sep 17 00:00:00 2001 From: Surafel Melese Date: Wed, 9 Aug 2023 18:25:06 +0300 Subject: [PATCH 04/11] feat: charge redered as curreny and event type col also added in payment table --- .../src/api/graphql-schemas.ts | 1 + .../ui/payments-component/payments-component.html | 12 +++++++++++- .../src/ui/payments-component/payments.component.ts | 1 + .../src/ui/queries.ts | 1 + 4 files changed, 14 insertions(+), 1 deletion(-) diff --git a/packages/vendure-plugin-stripe-subscription/src/api/graphql-schemas.ts b/packages/vendure-plugin-stripe-subscription/src/api/graphql-schemas.ts index ee54615b..23f893e5 100644 --- a/packages/vendure-plugin-stripe-subscription/src/api/graphql-schemas.ts +++ b/packages/vendure-plugin-stripe-subscription/src/api/graphql-schemas.ts @@ -61,6 +61,7 @@ const sharedTypes = gql` currency: String orderCode: String channelId: ID + eventType: String subscriptionId: String } input UpsertStripeSubscriptionScheduleInput { diff --git a/packages/vendure-plugin-stripe-subscription/src/ui/payments-component/payments-component.html b/packages/vendure-plugin-stripe-subscription/src/ui/payments-component/payments-component.html index 769dee2a..50693ac3 100644 --- a/packages/vendure-plugin-stripe-subscription/src/ui/payments-component/payments-component.html +++ b/packages/vendure-plugin-stripe-subscription/src/ui/payments-component/payments-component.html @@ -51,12 +51,21 @@ {{ payment.collectionMethod }} + + {{ payment.eventType }} + - {{ payment.charge }} + + {{ payment.charge | localeCurrency}} + {{ payment.subscriptionId }} diff --git a/packages/vendure-plugin-stripe-subscription/src/ui/payments-component/payments.component.ts b/packages/vendure-plugin-stripe-subscription/src/ui/payments-component/payments.component.ts index 290c01fd..1147f8c6 100644 --- a/packages/vendure-plugin-stripe-subscription/src/ui/payments-component/payments.component.ts +++ b/packages/vendure-plugin-stripe-subscription/src/ui/payments-component/payments.component.ts @@ -43,6 +43,7 @@ export class PaymentsComponent { name: 'orderCode' }, { name: 'channelId' }, { name: 'subscriptionId' }, + { name: 'eventType' }, ]) .connectToRoute(this.route); ngOnInit(): void { diff --git a/packages/vendure-plugin-stripe-subscription/src/ui/queries.ts b/packages/vendure-plugin-stripe-subscription/src/ui/queries.ts index 6bbf84e3..001c162c 100644 --- a/packages/vendure-plugin-stripe-subscription/src/ui/queries.ts +++ b/packages/vendure-plugin-stripe-subscription/src/ui/queries.ts @@ -27,6 +27,7 @@ export const PAYMENT_FRAGMENT = gql` collectionMethod charge currency + eventType orderCode channelId subscriptionId From fefbb78d2e4dbb889507535702d033eec3721386 Mon Sep 17 00:00:00 2001 From: Surafel Melese Date: Thu, 10 Aug 2023 08:40:22 +0300 Subject: [PATCH 05/11] feat: renamed method and added e2e test for payment to test after webhook payment success --- .../src/api/stripe-subscription.controller.ts | 2 +- .../src/api/stripe-subscription.service.ts | 2 +- .../test/stripe-subscription.spec.ts | 10 ++++++++++ 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/packages/vendure-plugin-stripe-subscription/src/api/stripe-subscription.controller.ts b/packages/vendure-plugin-stripe-subscription/src/api/stripe-subscription.controller.ts index e05c237e..248c1ed1 100644 --- a/packages/vendure-plugin-stripe-subscription/src/api/stripe-subscription.controller.ts +++ b/packages/vendure-plugin-stripe-subscription/src/api/stripe-subscription.controller.ts @@ -145,7 +145,7 @@ export class AdminResolver { @Ctx() ctx: RequestContext, @Args('options') options: StripeSubscriptionPaymentListOptions ): Promise { - return this.stripeSubscriptionService.getPayments(ctx, options); + return this.stripeSubscriptionService.getPaymentEvents(ctx, options); } @Allow(Permission.UpdateSettings) diff --git a/packages/vendure-plugin-stripe-subscription/src/api/stripe-subscription.service.ts b/packages/vendure-plugin-stripe-subscription/src/api/stripe-subscription.service.ts index 636ba4e8..793d6a97 100644 --- a/packages/vendure-plugin-stripe-subscription/src/api/stripe-subscription.service.ts +++ b/packages/vendure-plugin-stripe-subscription/src/api/stripe-subscription.service.ts @@ -432,7 +432,7 @@ export class StripeSubscriptionService { await stripeSubscriptionPaymentRepo.save(newPayment); } - async getPayments( + async getPaymentEvents( ctx: RequestContext, options: StripeSubscriptionPaymentListOptions ): Promise { diff --git a/packages/vendure-plugin-stripe-subscription/test/stripe-subscription.spec.ts b/packages/vendure-plugin-stripe-subscription/test/stripe-subscription.spec.ts index 43e5f852..5438137b 100644 --- a/packages/vendure-plugin-stripe-subscription/test/stripe-subscription.spec.ts +++ b/packages/vendure-plugin-stripe-subscription/test/stripe-subscription.spec.ts @@ -36,6 +36,7 @@ import { Schedule, StripeSubscriptionPlugin, StripeSubscriptionPricing, + StripeSubscriptionService, SubscriptionInterval, SubscriptionStartMoment, VariantForCalculation, @@ -57,6 +58,7 @@ import { UPDATE_VARIANT, } from './helpers'; import { expect, describe, beforeAll, afterAll, it, vi, test } from 'vitest'; +import { gql } from 'graphql-tag'; describe('Stripe Subscription Plugin', function () { let server: TestServer; @@ -760,6 +762,14 @@ describe('Stripe Subscription Plugin', function () { expect(subscriptionIds.length).toBe(3); }); + it('Should save payment event', async () => { + const ctx = await getDefaultCtx(server); + const paymentEvents = await server.app + .get(StripeSubscriptionService) + .getPaymentEvents(ctx, {}); + expect(paymentEvents.items?.length).toBeGreaterThan(0); + }); + it('Created paid in full subscription', async () => { const paidInFull = createdSubscriptions.find( (s) => s.description === 'Adult karate Paid in full' From 070be1766abeec75108be3257a934183eae79005 Mon Sep 17 00:00:00 2001 From: Surafel Melese Date: Fri, 11 Aug 2023 16:42:45 +0300 Subject: [PATCH 06/11] feat: updated vendure to 2.0.6 --- .../package.json | 8 +- yarn.lock | 100 ++++++++++++++---- 2 files changed, 83 insertions(+), 25 deletions(-) diff --git a/packages/vendure-plugin-stripe-subscription/package.json b/packages/vendure-plugin-stripe-subscription/package.json index ed6ff271..10475748 100644 --- a/packages/vendure-plugin-stripe-subscription/package.json +++ b/packages/vendure-plugin-stripe-subscription/package.json @@ -31,10 +31,10 @@ "@swc/core": "^1.3.59", "@types/localtunnel": "^2.0.1", "@types/nock": "^11.1.0", - "@vendure/admin-ui-plugin": "2.0.5", - "@vendure/core": "2.0.5", - "@vendure/testing": "2.0.5", - "@vendure/ui-devkit": "2.0.5", + "@vendure/admin-ui-plugin": "2.0.6", + "@vendure/core": "2.0.6", + "@vendure/testing": "2.0.6", + "@vendure/ui-devkit": "2.0.6", "copyfiles": "^2.4.1", "nock": "^13.2.9", "node-fetch": "^2.0.0", diff --git a/yarn.lock b/yarn.lock index b22db143..048fb744 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5162,15 +5162,15 @@ date-fns "^2.30.0" fs-extra "^10.0.0" -"@vendure/admin-ui-plugin@2.0.5": - version "2.0.5" - resolved "https://registry.yarnpkg.com/@vendure/admin-ui-plugin/-/admin-ui-plugin-2.0.5.tgz#34d33180db3fec330be5ad1f95e74ae897119c85" - integrity sha512-dNbfggTM9C7bzl8ZSQbQiQLL04rXrzqAuWWhB3NSCUUkJF+QLRKCHYEaMVkXe1kzcdEYx83CJg+S0H+ufANofw== +"@vendure/admin-ui-plugin@2.0.6": + version "2.0.6" + resolved "https://registry.yarnpkg.com/@vendure/admin-ui-plugin/-/admin-ui-plugin-2.0.6.tgz#2f96f670d18f03f716724e6b92cb876297a9232b" + integrity sha512-0aQTiMspNu/Zi/DD7b7ueMjRHDMocdveqGV0gEWXpcQ8J783AUmvXIOs7PwdP7/1aBLDAGm3LGyfjohFHiEmWg== dependencies: date-fns "^2.30.0" fs-extra "^10.0.0" -"@vendure/admin-ui@^2.0.4", "@vendure/admin-ui@^2.0.5": +"@vendure/admin-ui@^2.0.4": version "2.0.5" resolved "https://registry.yarnpkg.com/@vendure/admin-ui/-/admin-ui-2.0.5.tgz#d1e3a3f241410c2cd20548358691d8abe5b4175a" integrity sha512-UdVJNP2aFuzuFgR4kdon7STlHd9UWUen/w1A8tO1S46J8WuOCn08mNtX82WTcl9bloByMer4CGv99wz46VVtzw== @@ -5223,6 +5223,59 @@ tslib "^2.5.0" zone.js "~0.13.0" +"@vendure/admin-ui@^2.0.6": + version "2.0.6" + resolved "https://registry.yarnpkg.com/@vendure/admin-ui/-/admin-ui-2.0.6.tgz#9bbc591e711fc5ea3420b665744b2c61c1e40883" + integrity sha512-VCXV6f6Q6GsUVQNfKYo+N2Rs+R/cqOrG6wNEdUmSGGqUjKpq8djM79cAzAJCtCyA03jG7p+0QAd/kFZwLZmQ8g== + dependencies: + "@angular/animations" "^16.0.3" + "@angular/cdk" "^16.0.2" + "@angular/common" "^16.0.3" + "@angular/core" "^16.0.3" + "@angular/forms" "^16.0.3" + "@angular/language-service" "^16.0.3" + "@angular/platform-browser" "^16.0.3" + "@angular/platform-browser-dynamic" "^16.0.3" + "@angular/router" "^16.0.3" + "@apollo/client" "^3.7.9" + "@biesbjerg/ngx-translate-extract-marker" "^1.0.0" + "@cds/core" "^6.4.2" + "@clr/angular" "^15.4.0" + "@clr/core" "^4.0.15" + "@clr/icons" "^13.0.2" + "@clr/ui" "^15.4.0" + "@messageformat/core" "^3.1.0" + "@ng-select/ng-select" "^11.0.0" + "@ngx-translate/core" "^14.0.0" + "@ngx-translate/http-loader" "^7.0.0" + "@vendure/common" "^2.0.6" + "@webcomponents/custom-elements" "^1.5.1" + apollo-angular "^5.0.0" + apollo-upload-client "^17.0.0" + chartist "^1.3.0" + codejar "^3.7.0" + core-js "^3.29.0" + dayjs "^1.10.4" + graphql "16.6.0" + just-extend "^6.2.0" + messageformat "2.3.0" + ngx-pagination "^6.0.3" + ngx-translate-messageformat-compiler "^6.2.0" + prosemirror-commands "^1.5.1" + prosemirror-dropcursor "^1.7.1" + prosemirror-gapcursor "^1.3.1" + prosemirror-history "^1.3.0" + prosemirror-inputrules "^1.2.0" + prosemirror-keymap "^1.2.1" + prosemirror-menu "^1.2.1" + prosemirror-schema-basic "^1.2.1" + prosemirror-schema-list "^1.2.2" + prosemirror-state "^1.4.2" + prosemirror-tables "^1.3.2" + rxjs "^7.8.0" + tslib "^2.5.0" + zone.js "~0.13.0" + "@vendure/asset-server-plugin@2.0.4": version "2.0.4" resolved "https://registry.yarnpkg.com/@vendure/asset-server-plugin/-/asset-server-plugin-2.0.4.tgz#9a1f6289da493ef1e9cef7d9d90f5b93ce53dc04" @@ -5242,6 +5295,11 @@ resolved "https://registry.yarnpkg.com/@vendure/common/-/common-2.0.5.tgz#99e3135d41a698865a1eecbf80e2c70b0f6b1794" integrity sha512-S4kYKNwJM9DL5TlNZe9aJ3EiK5YPj6zXUqj0ebsQ+HJRHHarO8OK2oj964WprZNwCJDMbZItPzPTIPutnb915g== +"@vendure/common@^2.0.6": + version "2.0.6" + resolved "https://registry.yarnpkg.com/@vendure/common/-/common-2.0.6.tgz#4c71aedc30f13afe4f9938798a256aa5ab43aed6" + integrity sha512-/xdrTdKk5b4nZYGSzJKlYlVTxap2yaxPcE1bVTDdiDyse/wqIbkd76nIlCaYouVce80/3kTFj0nJaSR2QXjhDA== + "@vendure/core@2.0.4": version "2.0.4" resolved "https://registry.yarnpkg.com/@vendure/core/-/core-2.0.4.tgz#51b81105ef547c7a13397f03df3fdde16c9d76ff" @@ -5287,10 +5345,10 @@ rxjs "^7.5.4" typeorm "0.3.11" -"@vendure/core@2.0.5": - version "2.0.5" - resolved "https://registry.yarnpkg.com/@vendure/core/-/core-2.0.5.tgz#93099280e98fabd03b466b142d6c296ceb81f0a5" - integrity sha512-+IG+s2GRkfkxlEGR7UEbuuEwjRZMqOCJxvSd6NscUwqel39SIUnVSeETLEpg2tpVM5bRYKdDDIQXNQ7oDHwNOg== +"@vendure/core@2.0.6": + version "2.0.6" + resolved "https://registry.yarnpkg.com/@vendure/core/-/core-2.0.6.tgz#edd507387b38024445a6761ba22bac00c9f643de" + integrity sha512-5s+OLOoCxFgKmbz8xBRr7BQyuwvnMpBvKUlr1kLPoo4njY5vv3lXm/poYYloc3A1WELAa5fn28RNwfMQobBU4A== dependencies: "@graphql-tools/stitch" "^8.7.43" "@nestjs/apollo" "^10.2.0" @@ -5302,7 +5360,7 @@ "@nestjs/testing" "9.3.9" "@nestjs/typeorm" "9.0.1" "@types/fs-extra" "^9.0.1" - "@vendure/common" "^2.0.5" + "@vendure/common" "^2.0.6" apollo-server-express "3.6.3" bcrypt "^5.1.0" body-parser "^1.19.0" @@ -5360,14 +5418,14 @@ node-fetch "^2.6.0" sql.js "1.8.0" -"@vendure/testing@2.0.5": - version "2.0.5" - resolved "https://registry.yarnpkg.com/@vendure/testing/-/testing-2.0.5.tgz#de15aebc799d224d3dd90d2de71a55b00e3d9d16" - integrity sha512-PyHAKGZ1bUWB8TkiF49mTcrPMOtP7oUOWWm+jeBLlCffxs1KCZTB5nAURufl5xmhTKdThSF6OOP45CuQY7OaPg== +"@vendure/testing@2.0.6": + version "2.0.6" + resolved "https://registry.yarnpkg.com/@vendure/testing/-/testing-2.0.6.tgz#60071b2cf484f71fbc80a0292846b010e054c882" + integrity sha512-RQWUVGF/PxnW0BVHNpbKfEPQOYFvN65cM3u/H69Z92XWAH3hi90AAzuVGMxJxRdT01a4165OrQtJ4YUyKZhL0w== dependencies: "@graphql-typed-document-node/core" "^3.2.0" "@types/node-fetch" "^2.5.4" - "@vendure/common" "^2.0.5" + "@vendure/common" "^2.0.6" faker "^4.1.0" form-data "^3.0.0" graphql "16.6.0" @@ -5392,17 +5450,17 @@ glob "^9.2.1" rxjs "^7.5.4" -"@vendure/ui-devkit@2.0.5": - version "2.0.5" - resolved "https://registry.yarnpkg.com/@vendure/ui-devkit/-/ui-devkit-2.0.5.tgz#23e22891d3aa2c45ecc3487876dfe4173f9d4776" - integrity sha512-++jjou5QKwup6sOYG48jlDoqr++JudUnZNIfB5x+KjNnMGx+1o9QhV7CTMfA5f/y9RGiYYW4LmpMUAdTTKhAuA== +"@vendure/ui-devkit@2.0.6": + version "2.0.6" + resolved "https://registry.yarnpkg.com/@vendure/ui-devkit/-/ui-devkit-2.0.6.tgz#b4463d198597e237efbac0e6bd80d1e68a830c7a" + integrity sha512-CRQeox2W3snRRIA4z94M72fiZnt91jS+fc6woKBbem20DEUmDC2F7XEWjwED+jaGTkGbpON5f0wW5kj09GvQKw== dependencies: "@angular-devkit/build-angular" "^16.0.3" "@angular/cli" "^16.0.3" "@angular/compiler" "^16.0.3" "@angular/compiler-cli" "^16.0.3" - "@vendure/admin-ui" "^2.0.5" - "@vendure/common" "^2.0.5" + "@vendure/admin-ui" "^2.0.6" + "@vendure/common" "^2.0.6" chalk "^4.1.0" chokidar "^3.5.1" fs-extra "^10.0.0" From a90f633f05ac15a2367d32800548224da0e32195 Mon Sep 17 00:00:00 2001 From: Martijn Date: Tue, 15 Aug 2023 08:07:18 +0200 Subject: [PATCH 07/11] feat(metrics): this shouldnt have been on this branch --- .../src/api/metrics/average-order-value.ts | 44 ------------------- 1 file changed, 44 deletions(-) delete mode 100644 packages/vendure-plugin-metrics/src/api/metrics/average-order-value.ts diff --git a/packages/vendure-plugin-metrics/src/api/metrics/average-order-value.ts b/packages/vendure-plugin-metrics/src/api/metrics/average-order-value.ts deleted file mode 100644 index 0d05b858..00000000 --- a/packages/vendure-plugin-metrics/src/api/metrics/average-order-value.ts +++ /dev/null @@ -1,44 +0,0 @@ -import { Injector, Order, RequestContext } from '@vendure/core'; -import { - AdvancedMetricSummaryInput, - AdvancedMetricType, -} from '../../ui/generated/graphql'; -import { MetricStrategy } from '../metric-strategy'; - -/** - * Calculates the average order value per month - */ -export class AverageOrderValueMetric implements MetricStrategy { - readonly metricType: AdvancedMetricType = AdvancedMetricType.Currency; - readonly code = 'aov'; - - getTitle(ctx: RequestContext): string { - return `Average order value in ${ctx.channel.defaultCurrencyCode}`; - } - - sortByDateField(): string { - return 'orderPlacedAt'; - } - - loadData( - ctx: RequestContext, - injector: Injector, - from: Date, - to: Date, - input: AdvancedMetricSummaryInput - ): Promise { - throw new Error('Method not implemented.'); - } - - calculateDataPoint( - ctx: RequestContext, - data: Order[], - monthNr: number - ): number[] { - const total = data - .map((o) => o.totalWithTax) - .reduce((total, current) => total + current); - const average = Math.round(total / data.length) / 100; - return [average]; - } -} From f591a0429641e0eb6ffa7d8054e973c9135324da Mon Sep 17 00:00:00 2001 From: Martijn Date: Wed, 16 Aug 2023 08:33:33 +0200 Subject: [PATCH 08/11] fix(stripe-subscription): e2e test --- .../src/api/stripe-subscription.service.ts | 2 +- .../test/stripe-subscription.spec.ts | 19 ++++++++++--------- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/packages/vendure-plugin-stripe-subscription/src/api/stripe-subscription.service.ts b/packages/vendure-plugin-stripe-subscription/src/api/stripe-subscription.service.ts index 793d6a97..2210cc0e 100644 --- a/packages/vendure-plugin-stripe-subscription/src/api/stripe-subscription.service.ts +++ b/packages/vendure-plugin-stripe-subscription/src/api/stripe-subscription.service.ts @@ -413,7 +413,7 @@ export class StripeSubscriptionService { StripeSubscriptionPayment ); const charge = object.lines.data.reduce( - (acc, line) => acc + line.plan.amount, + (acc, line) => acc + (line.plan?.amount ?? 0), 0 ); const newPayment = new StripeSubscriptionPayment({ diff --git a/packages/vendure-plugin-stripe-subscription/test/stripe-subscription.spec.ts b/packages/vendure-plugin-stripe-subscription/test/stripe-subscription.spec.ts index 59a422e1..23c2129a 100644 --- a/packages/vendure-plugin-stripe-subscription/test/stripe-subscription.spec.ts +++ b/packages/vendure-plugin-stripe-subscription/test/stripe-subscription.spec.ts @@ -764,14 +764,6 @@ describe('Stripe Subscription Plugin', function () { expect(subscriptionIds.length).toBe(3); }); - it('Should save payment event', async () => { - const ctx = await getDefaultCtx(server); - const paymentEvents = await server.app - .get(StripeSubscriptionService) - .getPaymentEvents(ctx, {}); - expect(paymentEvents.items?.length).toBeGreaterThan(0); - }); - it('Created paid in full subscription', async () => { const paidInFull = createdSubscriptions.find( (s) => s.description === 'Adult karate Paid in full' @@ -844,7 +836,7 @@ describe('Stripe Subscription Plugin', function () { }); it('Logs payments to order history', async () => { - await adminClient.fetch( + const result = await adminClient.fetch( 'http://localhost:3050/stripe-subscriptions/webhook', { method: 'POST', @@ -872,6 +864,7 @@ describe('Stripe Subscription Plugin', function () { const history = await server.app .get(HistoryService) .getHistoryForOrder(ctx, 1, false); + expect(result.status).toBe(201); expect( history.items.find( (item) => item.data.message === 'Subscription payment failed' @@ -879,6 +872,14 @@ describe('Stripe Subscription Plugin', function () { ).toBeDefined(); }); + it('Should save payment event', async () => { + const ctx = await getDefaultCtx(server); + const paymentEvents = await server.app + .get(StripeSubscriptionService) + .getPaymentEvents(ctx, {}); + expect(paymentEvents.items?.length).toBeGreaterThan(0); + }); + it('Should cancel subscription', async () => { // Mock API let subscriptionRequests: any[] = []; From 0711823d39c0e369b08e1d0cdbfba67c223dcec4 Mon Sep 17 00:00:00 2001 From: Martijn Date: Wed, 16 Aug 2023 08:59:11 +0200 Subject: [PATCH 09/11] fix(stripe-subscription): increased version number --- .../package.json | 22 +- yarn.lock | 503 +----------------- 2 files changed, 27 insertions(+), 498 deletions(-) diff --git a/packages/vendure-plugin-stripe-subscription/package.json b/packages/vendure-plugin-stripe-subscription/package.json index 1af8ae9c..b435a5c8 100644 --- a/packages/vendure-plugin-stripe-subscription/package.json +++ b/packages/vendure-plugin-stripe-subscription/package.json @@ -1,6 +1,6 @@ { "name": "@pinelab/vendure-plugin-stripe-subscription", - "version": "1.1.1", + "version": "1.2.1", "description": "Vendure plugin for selling subscriptions via Stripe", "author": "Martijn van de Brug ", "homepage": "https://pinelab-plugins.com/", @@ -24,26 +24,6 @@ "start:no-admin": "yarn ts-node test/dev-server.ts", "generate": "graphql-codegen" }, - "devDependencies": { - "@graphql-codegen/cli": "^2.4.0", - "@graphql-codegen/typescript": "^2.4.8", - "@graphql-codegen/typescript-operations": "^2.3.5", - "@graphql-codegen/typed-document-node": "^5.0.1", - "@swc/core": "^1.3.59", - "@types/localtunnel": "^2.0.1", - "@types/nock": "^11.1.0", - "@vendure/admin-ui-plugin": "2.0.6", - "@vendure/core": "2.0.6", - "@vendure/testing": "2.0.6", - "@vendure/ui-devkit": "2.0.6", - "copyfiles": "^2.4.1", - "nock": "^13.2.9", - "node-fetch": "^2.0.0", - "ts-node": "^10.9.1", - "typescript": "4.9.5", - "unplugin-swc": "^1.3.2", - "vitest": "^0.30.1" - }, "dependencies": { "date-fns": "2.29.3", "stripe": "11.1.0" diff --git a/yarn.lock b/yarn.lock index 048fb744..21b82343 100644 --- a/yarn.lock +++ b/yarn.lock @@ -519,7 +519,7 @@ "@jridgewell/trace-mapping" "^0.3.17" jsesc "^2.5.1" -"@babel/generator@^7.14.0", "@babel/generator@^7.18.13", "@babel/generator@^7.22.5", "@babel/generator@^7.22.7", "@babel/generator@^7.22.9": +"@babel/generator@^7.14.0", "@babel/generator@^7.22.5", "@babel/generator@^7.22.7", "@babel/generator@^7.22.9": version "7.22.9" resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.22.9.tgz#572ecfa7a31002fa1de2a9d91621fd895da8493d" integrity sha512-KtLMbmicyuK2Ak/FTCJVbDnkN1SlT8/kceFTiuDiiRUUSMnHMidxSCdG4ndkTOHHpoomWe/4xkvHkEOncwjYIw== @@ -1494,7 +1494,7 @@ dependencies: regenerator-runtime "^0.13.11" -"@babel/template@7.22.5", "@babel/template@^7.18.10", "@babel/template@^7.22.5": +"@babel/template@7.22.5", "@babel/template@^7.22.5": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.22.5.tgz#0c8c4d944509875849bd0344ff0050756eefc6ec" integrity sha512-X7yV7eiwAxdj9k94NEylvbVHLiVG1nvzCV2EAowhxLTwODV1jl9UzZ48leOC0sH7OnuHrIkllaBgneUykIcZaw== @@ -1519,7 +1519,7 @@ debug "^4.1.0" globals "^11.1.0" -"@babel/types@^7.0.0", "@babel/types@^7.16.8", "@babel/types@^7.18.13", "@babel/types@^7.22.5", "@babel/types@^7.4.4": +"@babel/types@^7.0.0", "@babel/types@^7.16.8", "@babel/types@^7.22.5", "@babel/types@^7.4.4": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.22.5.tgz#cd93eeaab025880a3a47ec881f4b096a5b786fbe" integrity sha512-zo3MIHGOkPOfoRXitsgHLjEXmlDaD/5KU1Uzuc9GNiZPhSqVxVRtxuPaSBZDsYZ9qV88AjtMtWW7ww98loJ9KA== @@ -2199,47 +2199,6 @@ yaml "^1.10.0" yargs "^17.0.0" -"@graphql-codegen/cli@^2.4.0": - version "2.16.5" - resolved "https://registry.yarnpkg.com/@graphql-codegen/cli/-/cli-2.16.5.tgz#b3b5eeec357af01c1cb72f6a4ea96e52bd49e662" - integrity sha512-XYPIp+q7fB0xAGSAoRykiTe4oY80VU+z+dw5nuv4mLY0+pv7+pa2C6Nwhdw7a65lXOhFviBApWCCZeqd54SMnA== - dependencies: - "@babel/generator" "^7.18.13" - "@babel/template" "^7.18.10" - "@babel/types" "^7.18.13" - "@graphql-codegen/core" "^2.6.8" - "@graphql-codegen/plugin-helpers" "^3.1.2" - "@graphql-tools/apollo-engine-loader" "^7.3.6" - "@graphql-tools/code-file-loader" "^7.3.13" - "@graphql-tools/git-loader" "^7.2.13" - "@graphql-tools/github-loader" "^7.3.20" - "@graphql-tools/graphql-file-loader" "^7.5.0" - "@graphql-tools/json-file-loader" "^7.4.1" - "@graphql-tools/load" "^7.8.0" - "@graphql-tools/prisma-loader" "^7.2.49" - "@graphql-tools/url-loader" "^7.13.2" - "@graphql-tools/utils" "^9.0.0" - "@whatwg-node/fetch" "^0.6.0" - chalk "^4.1.0" - chokidar "^3.5.2" - cosmiconfig "^7.0.0" - cosmiconfig-typescript-loader "^4.3.0" - debounce "^1.2.0" - detect-indent "^6.0.0" - graphql-config "^4.4.0" - inquirer "^8.0.0" - is-glob "^4.0.1" - json-to-pretty-yaml "^1.2.2" - listr2 "^4.0.5" - log-symbols "^4.0.0" - shell-quote "^1.7.3" - string-env-interpolation "^1.0.1" - ts-log "^2.2.3" - ts-node "^10.9.1" - tslib "^2.4.0" - yaml "^1.10.0" - yargs "^17.0.0" - "@graphql-codegen/core@2.5.1": version "2.5.1" resolved "https://registry.yarnpkg.com/@graphql-codegen/core/-/core-2.5.1.tgz#e3d50d3449b8c58b74ea08e97faf656a1b7fc8a1" @@ -2250,16 +2209,6 @@ "@graphql-tools/utils" "^8.1.1" tslib "~2.3.0" -"@graphql-codegen/core@^2.6.8": - version "2.6.8" - resolved "https://registry.yarnpkg.com/@graphql-codegen/core/-/core-2.6.8.tgz#00c4011e3619ddbc6af5e41b2f254d6f6759556e" - integrity sha512-JKllNIipPrheRgl+/Hm/xuWMw9++xNQ12XJR/OHHgFopOg4zmN3TdlRSyYcv/K90hCFkkIwhlHFUQTfKrm8rxQ== - dependencies: - "@graphql-codegen/plugin-helpers" "^3.1.1" - "@graphql-tools/schema" "^9.0.0" - "@graphql-tools/utils" "^9.1.1" - tslib "~2.4.0" - "@graphql-codegen/plugin-helpers@^2.4.0", "@graphql-codegen/plugin-helpers@^2.4.1": version "2.7.2" resolved "https://registry.yarnpkg.com/@graphql-codegen/plugin-helpers/-/plugin-helpers-2.7.2.tgz#6544f739d725441c826a8af6a49519f588ff9bed" @@ -2272,7 +2221,7 @@ lodash "~4.17.0" tslib "~2.4.0" -"@graphql-codegen/plugin-helpers@^3.1.1", "@graphql-codegen/plugin-helpers@^3.1.2": +"@graphql-codegen/plugin-helpers@^3.1.2": version "3.1.2" resolved "https://registry.yarnpkg.com/@graphql-codegen/plugin-helpers/-/plugin-helpers-3.1.2.tgz#69a2e91178f478ea6849846ade0a59a844d34389" integrity sha512-emOQiHyIliVOIjKVKdsI5MXj312zmRDwmHpyUTZMjfpvxq/UVAHUJIVdVf+lnjjrI+LXBTgMlTWTgHQfmICxjg== @@ -2284,18 +2233,6 @@ lodash "~4.17.0" tslib "~2.4.0" -"@graphql-codegen/plugin-helpers@^5.0.0": - version "5.0.1" - resolved "https://registry.yarnpkg.com/@graphql-codegen/plugin-helpers/-/plugin-helpers-5.0.1.tgz#e2429fcfba3f078d5aa18aa062d46c922bbb0d55" - integrity sha512-6L5sb9D8wptZhnhLLBcheSPU7Tg//DGWgc5tQBWX46KYTOTQHGqDpv50FxAJJOyFVJrveN9otWk9UT9/yfY4ww== - dependencies: - "@graphql-tools/utils" "^10.0.0" - change-case-all "1.0.15" - common-tags "1.8.2" - import-from "4.0.0" - lodash "~4.17.0" - tslib "~2.5.0" - "@graphql-codegen/schema-ast@^2.4.1", "@graphql-codegen/schema-ast@^2.6.1": version "2.6.1" resolved "https://registry.yarnpkg.com/@graphql-codegen/schema-ast/-/schema-ast-2.6.1.tgz#8ba1b38827c034b51ecd3ce88622c2ae6cd3fe1a" @@ -2305,17 +2242,6 @@ "@graphql-tools/utils" "^9.0.0" tslib "~2.4.0" -"@graphql-codegen/typed-document-node@^5.0.1": - version "5.0.1" - resolved "https://registry.yarnpkg.com/@graphql-codegen/typed-document-node/-/typed-document-node-5.0.1.tgz#ac90cf67c61554f63ec100d6076b47c9f0b18b27" - integrity sha512-VFkhCuJnkgtbbgzoCAwTdJe2G1H6sd3LfCrDqWUrQe53y2ukfSb5Ov1PhAIkCBStKCMQBUY9YgGz9GKR40qQ8g== - dependencies: - "@graphql-codegen/plugin-helpers" "^5.0.0" - "@graphql-codegen/visitor-plugin-common" "4.0.1" - auto-bind "~4.0.0" - change-case-all "1.0.15" - tslib "~2.5.0" - "@graphql-codegen/typescript-document-nodes@2.2.8": version "2.2.8" resolved "https://registry.yarnpkg.com/@graphql-codegen/typescript-document-nodes/-/typescript-document-nodes-2.2.8.tgz#93a3eeb4064a323b3e510b2c9f7fe209831310da" @@ -2337,17 +2263,6 @@ auto-bind "~4.0.0" tslib "~2.3.0" -"@graphql-codegen/typescript-operations@^2.3.5": - version "2.5.13" - resolved "https://registry.yarnpkg.com/@graphql-codegen/typescript-operations/-/typescript-operations-2.5.13.tgz#f286c37f9c023356aacaa983ebd32e9e021a05ca" - integrity sha512-3vfR6Rx6iZU0JRt29GBkFlrSNTM6t+MSLF86ChvL4d/Jfo/JYAGuB3zNzPhirHYzJPCvLOAx2gy9ID1ltrpYiw== - dependencies: - "@graphql-codegen/plugin-helpers" "^3.1.2" - "@graphql-codegen/typescript" "^2.8.8" - "@graphql-codegen/visitor-plugin-common" "2.13.8" - auto-bind "~4.0.0" - tslib "~2.4.0" - "@graphql-codegen/typescript@2.4.8": version "2.4.8" resolved "https://registry.yarnpkg.com/@graphql-codegen/typescript/-/typescript-2.4.8.tgz#e8110baba9713cde72d57a5c95aa27400363ed9a" @@ -2359,7 +2274,7 @@ auto-bind "~4.0.0" tslib "~2.3.0" -"@graphql-codegen/typescript@^2.4.8", "@graphql-codegen/typescript@^2.8.8": +"@graphql-codegen/typescript@^2.4.8": version "2.8.8" resolved "https://registry.yarnpkg.com/@graphql-codegen/typescript/-/typescript-2.8.8.tgz#8c3b9153e334db43c65f8f31ced69b4c60d14861" integrity sha512-A0oUi3Oy6+DormOlrTC4orxT9OBZkIglhbJBcDmk34jAKKUgesukXRd4yOhmTrnbchpXz2T8IAOFB3FWIaK4Rw== @@ -2402,23 +2317,7 @@ parse-filepath "^1.0.2" tslib "~2.3.0" -"@graphql-codegen/visitor-plugin-common@4.0.1": - version "4.0.1" - resolved "https://registry.yarnpkg.com/@graphql-codegen/visitor-plugin-common/-/visitor-plugin-common-4.0.1.tgz#64e293728b3c186f6767141e41fcdb310e50d367" - integrity sha512-Bi/1z0nHg4QMsAqAJhds+ForyLtk7A3HQOlkrZNm3xEkY7lcBzPtiOTLBtvziwopBsXUxqeSwVjOOFPLS5Yw1Q== - dependencies: - "@graphql-codegen/plugin-helpers" "^5.0.0" - "@graphql-tools/optimize" "^2.0.0" - "@graphql-tools/relay-operation-optimizer" "^7.0.0" - "@graphql-tools/utils" "^10.0.0" - auto-bind "~4.0.0" - change-case-all "1.0.15" - dependency-graph "^0.11.0" - graphql-tag "^2.11.0" - parse-filepath "^1.0.2" - tslib "~2.5.0" - -"@graphql-tools/apollo-engine-loader@^7.0.5", "@graphql-tools/apollo-engine-loader@^7.3.6": +"@graphql-tools/apollo-engine-loader@^7.0.5": version "7.3.26" resolved "https://registry.yarnpkg.com/@graphql-tools/apollo-engine-loader/-/apollo-engine-loader-7.3.26.tgz#91e54460d5579933e42a2010b8688c3459c245d8" integrity sha512-h1vfhdJFjnCYn9b5EY1Z91JTF0KB3hHVJNQIsiUV2mpQXZdeOXQoaWeYEKaiI5R6kwBw5PP9B0fv3jfUIG8LyQ== @@ -2449,7 +2348,7 @@ tslib "^2.4.0" value-or-promise "^1.0.12" -"@graphql-tools/code-file-loader@^7.0.6", "@graphql-tools/code-file-loader@^7.3.13": +"@graphql-tools/code-file-loader@^7.0.6": version "7.3.23" resolved "https://registry.yarnpkg.com/@graphql-tools/code-file-loader/-/code-file-loader-7.3.23.tgz#33793f9a1f8e74981f8ae6ec4ab7061f9713db15" integrity sha512-8Wt1rTtyTEs0p47uzsPJ1vAtfAx0jmxPifiNdmo9EOCuUPyQGEbMaik/YkqZ7QUFIEYEQu+Vgfo8tElwOPtx5Q== @@ -2522,7 +2421,7 @@ tslib "^2.4.0" value-or-promise "^1.0.12" -"@graphql-tools/git-loader@^7.0.5", "@graphql-tools/git-loader@^7.2.13": +"@graphql-tools/git-loader@^7.0.5": version "7.3.0" resolved "https://registry.yarnpkg.com/@graphql-tools/git-loader/-/git-loader-7.3.0.tgz#ca10c17d4f58c4592432d9d2ac1c2b393aebad16" integrity sha512-gcGAK+u16eHkwsMYqqghZbmDquh8QaO24Scsxq+cVR+vx1ekRlsEiXvu+yXVDbZdcJ6PBIbeLcQbEu+xhDLmvQ== @@ -2534,7 +2433,7 @@ tslib "^2.4.0" unixify "^1.0.0" -"@graphql-tools/github-loader@^7.0.5", "@graphql-tools/github-loader@^7.3.20": +"@graphql-tools/github-loader@^7.0.5": version "7.3.28" resolved "https://registry.yarnpkg.com/@graphql-tools/github-loader/-/github-loader-7.3.28.tgz#a7166b136e8442bd8b3ab943ad3b66c84bcabfcf" integrity sha512-OK92Lf9pmxPQvjUNv05b3tnVhw0JRfPqOf15jZjyQ8BfdEUrJoP32b4dRQQem/wyRL24KY4wOfArJNqzpsbwCA== @@ -2547,7 +2446,7 @@ tslib "^2.4.0" value-or-promise "^1.0.12" -"@graphql-tools/graphql-file-loader@^7.0.5", "@graphql-tools/graphql-file-loader@^7.3.7", "@graphql-tools/graphql-file-loader@^7.5.0": +"@graphql-tools/graphql-file-loader@^7.0.5", "@graphql-tools/graphql-file-loader@^7.3.7": version "7.5.17" resolved "https://registry.yarnpkg.com/@graphql-tools/graphql-file-loader/-/graphql-file-loader-7.5.17.tgz#7c281617ea3ab4db4d42a2bdb49850f2b937f0f9" integrity sha512-hVwwxPf41zOYgm4gdaZILCYnKB9Zap7Ys9OhY1hbwuAuC4MMNY9GpUjoTU3CQc3zUiPoYStyRtUGkHSJZ3HxBw== @@ -2579,7 +2478,7 @@ resolve-from "5.0.0" tslib "^2.4.0" -"@graphql-tools/json-file-loader@^7.1.2", "@graphql-tools/json-file-loader@^7.3.7", "@graphql-tools/json-file-loader@^7.4.1": +"@graphql-tools/json-file-loader@^7.1.2", "@graphql-tools/json-file-loader@^7.3.7": version "7.4.18" resolved "https://registry.yarnpkg.com/@graphql-tools/json-file-loader/-/json-file-loader-7.4.18.tgz#d78ae40979bde51cfc59717757354afc9e35fba2" integrity sha512-AJ1b6Y1wiVgkwsxT5dELXhIVUPs/u3VZ8/0/oOtpcoyO/vAeM5rOvvWegzicOOnQw8G45fgBRMkkRfeuwVt6+w== @@ -2589,7 +2488,7 @@ tslib "^2.4.0" unixify "^1.0.0" -"@graphql-tools/load@^7.3.0", "@graphql-tools/load@^7.5.5", "@graphql-tools/load@^7.8.0": +"@graphql-tools/load@^7.3.0", "@graphql-tools/load@^7.5.5": version "7.8.14" resolved "https://registry.yarnpkg.com/@graphql-tools/load/-/load-7.8.14.tgz#f2356f9a5f658a42e33934ae036e4b2cadf2d1e9" integrity sha512-ASQvP+snHMYm+FhIaLxxFgVdRaM0vrN9wW2BKInQpktwWTXVyk+yP5nQUCEGmn0RTdlPKrffBaigxepkEAJPrg== @@ -2640,14 +2539,7 @@ dependencies: tslib "^2.4.0" -"@graphql-tools/optimize@^2.0.0": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@graphql-tools/optimize/-/optimize-2.0.0.tgz#7a9779d180824511248a50c5a241eff6e7a2d906" - integrity sha512-nhdT+CRGDZ+bk68ic+Jw1OZ99YCDIKYA5AlVAnBHJvMawSx9YQqQAIj4refNc1/LRieGiuWvhbG3jvPVYho0Dg== - dependencies: - tslib "^2.4.0" - -"@graphql-tools/prisma-loader@^7.0.6", "@graphql-tools/prisma-loader@^7.2.49": +"@graphql-tools/prisma-loader@^7.0.6": version "7.2.72" resolved "https://registry.yarnpkg.com/@graphql-tools/prisma-loader/-/prisma-loader-7.2.72.tgz#6304fc23600458396f3ede713d8e2371df7850e3" integrity sha512-0a7uV7Fky6yDqd0tI9+XMuvgIo6GAqiVzzzFV4OSLry4AwiQlI3igYseBV7ZVOGhedOTqj/URxjpiv07hRcwag== @@ -2680,15 +2572,6 @@ "@graphql-tools/utils" "^9.2.1" tslib "^2.4.0" -"@graphql-tools/relay-operation-optimizer@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@graphql-tools/relay-operation-optimizer/-/relay-operation-optimizer-7.0.0.tgz#24367666af87bc5a81748de5e8e9b3c523fd4207" - integrity sha512-UNlJi5y3JylhVWU4MBpL0Hun4Q7IoJwv9xYtmAz+CgRa066szzY7dcuPfxrA7cIGgG/Q6TVsKsYaiF4OHPs1Fw== - dependencies: - "@ardatan/relay-compiler" "12.0.0" - "@graphql-tools/utils" "^10.0.0" - tslib "^2.4.0" - "@graphql-tools/schema@9.0.16": version "9.0.16" resolved "https://registry.yarnpkg.com/@graphql-tools/schema/-/schema-9.0.16.tgz#7d340d69e6094dc01a2b9e625c7bb4fff89ea521" @@ -2709,7 +2592,7 @@ tslib "^2.4.0" value-or-promise "1.0.11" -"@graphql-tools/schema@^9.0.0", "@graphql-tools/schema@^9.0.18", "@graphql-tools/schema@^9.0.19": +"@graphql-tools/schema@^9.0.18", "@graphql-tools/schema@^9.0.19": version "9.0.19" resolved "https://registry.yarnpkg.com/@graphql-tools/schema/-/schema-9.0.19.tgz#c4ad373b5e1b8a0cf365163435b7d236ebdd06e7" integrity sha512-oBRPoNBtCkk0zbUsyP4GaIzCt8C0aCI4ycIRUL67KK5pOHljKLBBtGT+Jr6hkzA74C8Gco8bpZPe7aWFjiaK2w== @@ -2734,7 +2617,7 @@ tslib "^2.4.0" value-or-promise "^1.0.11" -"@graphql-tools/url-loader@^7.0.11", "@graphql-tools/url-loader@^7.13.2", "@graphql-tools/url-loader@^7.17.18", "@graphql-tools/url-loader@^7.9.7": +"@graphql-tools/url-loader@^7.0.11", "@graphql-tools/url-loader@^7.17.18", "@graphql-tools/url-loader@^7.9.7": version "7.17.18" resolved "https://registry.yarnpkg.com/@graphql-tools/url-loader/-/url-loader-7.17.18.tgz#3e253594d23483e4c0dd3a4c3dd2ad5cd0141192" integrity sha512-ear0CiyTj04jCVAxi7TvgbnGDIN2HgqzXzwsfcqiVg9cvjT40NcMlZ2P1lZDgqMkZ9oyLTV8Bw6j+SyG6A+xPw== @@ -2760,7 +2643,7 @@ dependencies: tslib "^2.4.0" -"@graphql-tools/utils@9.2.1", "@graphql-tools/utils@^9.0.0", "@graphql-tools/utils@^9.1.1", "@graphql-tools/utils@^9.2.1": +"@graphql-tools/utils@9.2.1", "@graphql-tools/utils@^9.0.0", "@graphql-tools/utils@^9.2.1": version "9.2.1" resolved "https://registry.yarnpkg.com/@graphql-tools/utils/-/utils-9.2.1.tgz#1b3df0ef166cfa3eae706e3518b17d5922721c57" integrity sha512-WUw506Ql6xzmOORlriNrD6Ugx+HjVgYxt9KCXD9mHAak+eaXSwuGGPyE60hy9xaDEoXKBsG7SkG69ybitaVl6A== @@ -2768,15 +2651,6 @@ "@graphql-typed-document-node/core" "^3.1.1" tslib "^2.4.0" -"@graphql-tools/utils@^10.0.0": - version "10.0.4" - resolved "https://registry.yarnpkg.com/@graphql-tools/utils/-/utils-10.0.4.tgz#3104bea54752ae54f1f4a67833d7e3b734400dbe" - integrity sha512-MF+nZgGROSnFgyOYWhrl2PuJMlIBvaCH48vtnlnDQKSeDc2fUfOzUVloBAQvnYmK9JBmHHks4Pxv25Ybg3r45Q== - dependencies: - "@graphql-typed-document-node/core" "^3.1.1" - dset "^3.1.2" - tslib "^2.4.0" - "@graphql-tools/utils@^8.1.1", "@graphql-tools/utils@^8.3.0", "@graphql-tools/utils@^8.8.0": version "8.13.1" resolved "https://registry.yarnpkg.com/@graphql-tools/utils/-/utils-8.13.1.tgz#b247607e400365c2cd87ff54654d4ad25a7ac491" @@ -4433,101 +4307,51 @@ resolved "https://registry.yarnpkg.com/@swc/core-darwin-arm64/-/core-darwin-arm64-1.3.59.tgz#04137eaf3549a2c195a4eeff409687379d927809" integrity sha512-AnqWFBgEKHP0jb4iZqx7eVQT9/rX45+DE4Ox7GpwCahUKxxrsDLyXzKhwLwQuAjUvtu5JcSB77szKpPGDM49fQ== -"@swc/core-darwin-arm64@1.3.74": - version "1.3.74" - resolved "https://registry.yarnpkg.com/@swc/core-darwin-arm64/-/core-darwin-arm64-1.3.74.tgz#5ec6f504fb8cd74fd5133080f6cc670327a867cd" - integrity sha512-2rMV4QxM583jXcREfo0MhV3Oj5pgRSfSh/kVrB1twL2rQxOrbzkAPT/8flmygdVoL4f2F7o1EY5lKlYxEBiIKQ== - "@swc/core-darwin-x64@1.3.59": version "1.3.59" resolved "https://registry.yarnpkg.com/@swc/core-darwin-x64/-/core-darwin-x64-1.3.59.tgz#edd5b4e33f7caa2b67a4989934fe7bc8e24d79dd" integrity sha512-iqDs+yii9mOsmpJez82SEi4d4prWDRlapHxKnDVJ0x1AqRo41vIq8t3fujrvCHYU5VQgOYGh4ooXQpaP2H3B2A== -"@swc/core-darwin-x64@1.3.74": - version "1.3.74" - resolved "https://registry.yarnpkg.com/@swc/core-darwin-x64/-/core-darwin-x64-1.3.74.tgz#5da7bdc4ad0fb3b4375d9c1039672ae8f61efaeb" - integrity sha512-KKEGE1wXneYXe15fWDRM8/oekd/Q4yAuccA0vWY/7i6nOSPqWYcSDR0nRtR030ltDxWt0rk/eCTmNkrOWrKs3A== - "@swc/core-linux-arm-gnueabihf@1.3.59": version "1.3.59" resolved "https://registry.yarnpkg.com/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.3.59.tgz#448c1c09f9d25e416e431fe1a627c2fc1abd1251" integrity sha512-PB0PP+SgkCSd/kYmltnPiGv42cOSaih1OjXCEjxvNwUFEmWqluW6uGdWaNiR1LoYMxhcHZTc336jL2+O3l6p0Q== -"@swc/core-linux-arm-gnueabihf@1.3.74": - version "1.3.74" - resolved "https://registry.yarnpkg.com/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.3.74.tgz#52d818692aaaf9138e1175956271cae8107c1096" - integrity sha512-HehH5DR6r/5fIVu7tu8ZqgrHkhSCQNewf1ztFQJgcmaQWn+H4AJERBjwkjosqh4TvUJucZv8vyRTvrFeBXaCSA== - "@swc/core-linux-arm64-gnu@1.3.59": version "1.3.59" resolved "https://registry.yarnpkg.com/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.3.59.tgz#78061652c93f64cf7d6488a18caaffb98e94d8e1" integrity sha512-Ol/JPszWZ+OZ44FOdJe35TfJ1ckG4pYaisZJ4E7PzfwfVe2ygX85C5WWR4e5L0Y1zFvzpcI7gdyC2wzcXk4Cig== -"@swc/core-linux-arm64-gnu@1.3.74": - version "1.3.74" - resolved "https://registry.yarnpkg.com/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.3.74.tgz#b230ba8623edb3c4b9ceffaf9aced8bf7a9fc829" - integrity sha512-+xkbCRz/wczgdknoV4NwYxbRI2dD7x/qkIFcVM2buzLCq8oWLweuV8+aL4pRqu0qDh7ZSb1jcaVTUIsySCJznA== - "@swc/core-linux-arm64-musl@1.3.59": version "1.3.59" resolved "https://registry.yarnpkg.com/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.3.59.tgz#496a939129243b51e1e1ff90cdcc1c1437e71d6f" integrity sha512-PtTTtGbj9GiY5gJdoSFL2A0vL6BRaS1haAhp6g3hZvLDkTTg+rJURmzwBMMjaQlnGC62x/lLf6MoszHG/05//Q== -"@swc/core-linux-arm64-musl@1.3.74": - version "1.3.74" - resolved "https://registry.yarnpkg.com/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.3.74.tgz#05ff0f3046aba1dd9d2d8793c10cd4a21a46fd7f" - integrity sha512-maKFZSCD3tQznzPV7T3V+TtiWZFEFM8YrnSS5fQNNb+K9J65sL+170uTb3M7H4cFkG+9Sm5k5yCrCIutlvV48g== - "@swc/core-linux-x64-gnu@1.3.59": version "1.3.59" resolved "https://registry.yarnpkg.com/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.3.59.tgz#4e12cab7e6a49d52321eac9d10787cdb8cadce0f" integrity sha512-XBW9AGi0YsIN76IfesnDSBn/5sjR69J75KUNte8sH6seYlHJ0/kblqUMbUcfr0CiGoJadbzAZeKZZmfN7EsHpg== -"@swc/core-linux-x64-gnu@1.3.74": - version "1.3.74" - resolved "https://registry.yarnpkg.com/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.3.74.tgz#a98d9a984d47404aa2de478dd3cd33dbd195bba2" - integrity sha512-LEXpcShF6DLTWJSiBhMSYZkLQ27UvaQ24fCFhoIV/R3dhYaUpHmIyLPPBNC82T03lB3ONUFVwrRw6fxDJ/f00A== - "@swc/core-linux-x64-musl@1.3.59": version "1.3.59" resolved "https://registry.yarnpkg.com/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.3.59.tgz#8e29ade3599c5215d1c04507e59761aa5c95a9eb" integrity sha512-Cy5E939SdWPQ34cg6UABNO0RyEe0FuWqzZ/GLKtK11Ir4fjttVlucZiY59uQNyUVUc8T2qE0VBFCyD/zYGuHtg== -"@swc/core-linux-x64-musl@1.3.74": - version "1.3.74" - resolved "https://registry.yarnpkg.com/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.3.74.tgz#95e04431eba994b4fae23c578ad1ba73fb72c21d" - integrity sha512-sxsFctbFMZEFmDE7CmYljG0dMumH8XBTwwtGr8s6z0fYAzXBGNq2AFPcmEh2np9rPWkt7pE1m0ByESD+dMkbxQ== - "@swc/core-win32-arm64-msvc@1.3.59": version "1.3.59" resolved "https://registry.yarnpkg.com/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.3.59.tgz#c0b94236288e8e596628b821194ee80372cf0fdb" integrity sha512-z5ZJxizRvRoSAaevRIi3YjQh74OFWEIhonSDWNdqDL7RbjEivcatYcG7OikH6s+rtPhOcwNm3PbGV2Prcgh/gg== -"@swc/core-win32-arm64-msvc@1.3.74": - version "1.3.74" - resolved "https://registry.yarnpkg.com/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.3.74.tgz#62cb708094a8902a307fba6eea08682dbccd472d" - integrity sha512-F7hY9/BjFCozA4YPFYFH5FGCyWwa44vIXHqG66F5cDwXDGFn8ZtBsYIsiPfUYcx0AeAo1ojnVWKPxokZhYNYqA== - "@swc/core-win32-ia32-msvc@1.3.59": version "1.3.59" resolved "https://registry.yarnpkg.com/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.3.59.tgz#f806824d840c2029354fd662b0f4eeb51836a9ef" integrity sha512-vxpsn+hrKAhi5YusQfB/JXUJJVX40rIRE/L49ilBEqdbH8Khkoego6AD+2vWqTdJcUHo1WiAIAEZ0rTsjyorLQ== -"@swc/core-win32-ia32-msvc@1.3.74": - version "1.3.74" - resolved "https://registry.yarnpkg.com/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.3.74.tgz#fe5a2d8bbddb609e554e0d8d678093973096330c" - integrity sha512-qBAsiD1AlIdqED6wy3UNRHyAys9pWMUidX0LJ6mj24r/vfrzzTBAUrLJe5m7bzE+F1Rgi001avYJeEW1DLEJ+Q== - "@swc/core-win32-x64-msvc@1.3.59": version "1.3.59" resolved "https://registry.yarnpkg.com/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.3.59.tgz#f8a21d9048a3652c058880649e174c7a5589fae6" integrity sha512-Ris/cJbURylcLwqz4RZUUBCEGsuaIHOJsvf69W5pGKHKBryVoOTNhBKpo3Km2hoAi5qFQ/ou0trAT4hBsVPZvQ== -"@swc/core-win32-x64-msvc@1.3.74": - version "1.3.74" - resolved "https://registry.yarnpkg.com/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.3.74.tgz#4fd459c7264d4c97d1b2965ed6aa86b1725ce38b" - integrity sha512-S3YAvvLprTnPRwQuy9Dkwubb5SRLpVK3JJsqYDbGfgj8PGQyKHZcVJ5X3nfFsoWLy3j9B/3Os2nawprRSzeC5A== - "@swc/core@1.3.59": version "1.3.59" resolved "https://registry.yarnpkg.com/@swc/core/-/core-1.3.59.tgz#0e73e320faf4ca881f51c1820e34e0998b720efc" @@ -4544,22 +4368,6 @@ "@swc/core-win32-ia32-msvc" "1.3.59" "@swc/core-win32-x64-msvc" "1.3.59" -"@swc/core@^1.3.59": - version "1.3.74" - resolved "https://registry.yarnpkg.com/@swc/core/-/core-1.3.74.tgz#b1d1a3c46ca32b7f10d970c8a209d2913c9de251" - integrity sha512-P+MIExOTdWlfq8Heb1/NhBAke6UTckd4cRDuJoFcFMGBRvgoCMNWhnfP3FRRXPLI7GGg27dRZS+xHiqYyQmSrA== - optionalDependencies: - "@swc/core-darwin-arm64" "1.3.74" - "@swc/core-darwin-x64" "1.3.74" - "@swc/core-linux-arm-gnueabihf" "1.3.74" - "@swc/core-linux-arm64-gnu" "1.3.74" - "@swc/core-linux-arm64-musl" "1.3.74" - "@swc/core-linux-x64-gnu" "1.3.74" - "@swc/core-linux-x64-musl" "1.3.74" - "@swc/core-win32-arm64-msvc" "1.3.74" - "@swc/core-win32-ia32-msvc" "1.3.74" - "@swc/core-win32-x64-msvc" "1.3.74" - "@szmarczak/http-timer@^1.1.2": version "1.1.2" resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-1.1.2.tgz#b1665e2c461a2cd92f4c1bbf50d5454de0d4b421" @@ -4810,13 +4618,6 @@ resolved "https://registry.yarnpkg.com/@types/linkify-it/-/linkify-it-3.0.2.tgz#fd2cd2edbaa7eaac7e7f3c1748b52a19143846c9" integrity sha512-HZQYqbiFVWufzCwexrvh694SOim8z2d+xJl5UNamcvQFejLY/2YUtzXHYi3cHdI7PMlS8ejH2slRAOJQ32aNbA== -"@types/localtunnel@^2.0.1": - version "2.0.1" - resolved "https://registry.yarnpkg.com/@types/localtunnel/-/localtunnel-2.0.1.tgz#c28a067de1da81b0b4730a9fc2f98e067f973996" - integrity sha512-0h/ggh+tp9uKHc2eEOLdMgWW0cNwsQfn6iEE1Y44FszNB4BQyL5N6xvd5BnChZksB0YgVqa5MKxJt0dFoOKRxw== - dependencies: - "@types/node" "*" - "@types/long@^4.0.0", "@types/long@^4.0.1": version "4.0.2" resolved "https://registry.yarnpkg.com/@types/long/-/long-4.0.2.tgz#b74129719fc8d11c01868010082d483b7545591a" @@ -4860,13 +4661,6 @@ resolved "https://registry.yarnpkg.com/@types/minimist/-/minimist-1.2.2.tgz#ee771e2ba4b3dc5b372935d549fd9617bf345b8c" integrity sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ== -"@types/nock@^11.1.0": - version "11.1.0" - resolved "https://registry.yarnpkg.com/@types/nock/-/nock-11.1.0.tgz#0a8c1056a31ba32a959843abccf99626dd90a538" - integrity sha512-jI/ewavBQ7X5178262JQR0ewicPAcJhXS/iFaNJl0VHLfyosZ/kwSrsa6VNQNSO8i9d8SqdRgOtZSOKJ/+iNMw== - dependencies: - nock "*" - "@types/node-fetch@^2.5.4": version "2.6.4" resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.6.4.tgz#1bc3a26de814f6bf466b25aeb1473fa1afe6a660" @@ -5162,14 +4956,6 @@ date-fns "^2.30.0" fs-extra "^10.0.0" -"@vendure/admin-ui-plugin@2.0.6": - version "2.0.6" - resolved "https://registry.yarnpkg.com/@vendure/admin-ui-plugin/-/admin-ui-plugin-2.0.6.tgz#2f96f670d18f03f716724e6b92cb876297a9232b" - integrity sha512-0aQTiMspNu/Zi/DD7b7ueMjRHDMocdveqGV0gEWXpcQ8J783AUmvXIOs7PwdP7/1aBLDAGm3LGyfjohFHiEmWg== - dependencies: - date-fns "^2.30.0" - fs-extra "^10.0.0" - "@vendure/admin-ui@^2.0.4": version "2.0.5" resolved "https://registry.yarnpkg.com/@vendure/admin-ui/-/admin-ui-2.0.5.tgz#d1e3a3f241410c2cd20548358691d8abe5b4175a" @@ -5223,59 +5009,6 @@ tslib "^2.5.0" zone.js "~0.13.0" -"@vendure/admin-ui@^2.0.6": - version "2.0.6" - resolved "https://registry.yarnpkg.com/@vendure/admin-ui/-/admin-ui-2.0.6.tgz#9bbc591e711fc5ea3420b665744b2c61c1e40883" - integrity sha512-VCXV6f6Q6GsUVQNfKYo+N2Rs+R/cqOrG6wNEdUmSGGqUjKpq8djM79cAzAJCtCyA03jG7p+0QAd/kFZwLZmQ8g== - dependencies: - "@angular/animations" "^16.0.3" - "@angular/cdk" "^16.0.2" - "@angular/common" "^16.0.3" - "@angular/core" "^16.0.3" - "@angular/forms" "^16.0.3" - "@angular/language-service" "^16.0.3" - "@angular/platform-browser" "^16.0.3" - "@angular/platform-browser-dynamic" "^16.0.3" - "@angular/router" "^16.0.3" - "@apollo/client" "^3.7.9" - "@biesbjerg/ngx-translate-extract-marker" "^1.0.0" - "@cds/core" "^6.4.2" - "@clr/angular" "^15.4.0" - "@clr/core" "^4.0.15" - "@clr/icons" "^13.0.2" - "@clr/ui" "^15.4.0" - "@messageformat/core" "^3.1.0" - "@ng-select/ng-select" "^11.0.0" - "@ngx-translate/core" "^14.0.0" - "@ngx-translate/http-loader" "^7.0.0" - "@vendure/common" "^2.0.6" - "@webcomponents/custom-elements" "^1.5.1" - apollo-angular "^5.0.0" - apollo-upload-client "^17.0.0" - chartist "^1.3.0" - codejar "^3.7.0" - core-js "^3.29.0" - dayjs "^1.10.4" - graphql "16.6.0" - just-extend "^6.2.0" - messageformat "2.3.0" - ngx-pagination "^6.0.3" - ngx-translate-messageformat-compiler "^6.2.0" - prosemirror-commands "^1.5.1" - prosemirror-dropcursor "^1.7.1" - prosemirror-gapcursor "^1.3.1" - prosemirror-history "^1.3.0" - prosemirror-inputrules "^1.2.0" - prosemirror-keymap "^1.2.1" - prosemirror-menu "^1.2.1" - prosemirror-schema-basic "^1.2.1" - prosemirror-schema-list "^1.2.2" - prosemirror-state "^1.4.2" - prosemirror-tables "^1.3.2" - rxjs "^7.8.0" - tslib "^2.5.0" - zone.js "~0.13.0" - "@vendure/asset-server-plugin@2.0.4": version "2.0.4" resolved "https://registry.yarnpkg.com/@vendure/asset-server-plugin/-/asset-server-plugin-2.0.4.tgz#9a1f6289da493ef1e9cef7d9d90f5b93ce53dc04" @@ -5295,11 +5028,6 @@ resolved "https://registry.yarnpkg.com/@vendure/common/-/common-2.0.5.tgz#99e3135d41a698865a1eecbf80e2c70b0f6b1794" integrity sha512-S4kYKNwJM9DL5TlNZe9aJ3EiK5YPj6zXUqj0ebsQ+HJRHHarO8OK2oj964WprZNwCJDMbZItPzPTIPutnb915g== -"@vendure/common@^2.0.6": - version "2.0.6" - resolved "https://registry.yarnpkg.com/@vendure/common/-/common-2.0.6.tgz#4c71aedc30f13afe4f9938798a256aa5ab43aed6" - integrity sha512-/xdrTdKk5b4nZYGSzJKlYlVTxap2yaxPcE1bVTDdiDyse/wqIbkd76nIlCaYouVce80/3kTFj0nJaSR2QXjhDA== - "@vendure/core@2.0.4": version "2.0.4" resolved "https://registry.yarnpkg.com/@vendure/core/-/core-2.0.4.tgz#51b81105ef547c7a13397f03df3fdde16c9d76ff" @@ -5345,51 +5073,6 @@ rxjs "^7.5.4" typeorm "0.3.11" -"@vendure/core@2.0.6": - version "2.0.6" - resolved "https://registry.yarnpkg.com/@vendure/core/-/core-2.0.6.tgz#edd507387b38024445a6761ba22bac00c9f643de" - integrity sha512-5s+OLOoCxFgKmbz8xBRr7BQyuwvnMpBvKUlr1kLPoo4njY5vv3lXm/poYYloc3A1WELAa5fn28RNwfMQobBU4A== - dependencies: - "@graphql-tools/stitch" "^8.7.43" - "@nestjs/apollo" "^10.2.0" - "@nestjs/common" "9.3.9" - "@nestjs/core" "9.3.9" - "@nestjs/graphql" "10.2.0" - "@nestjs/platform-express" "9.3.9" - "@nestjs/terminus" "9.2.1" - "@nestjs/testing" "9.3.9" - "@nestjs/typeorm" "9.0.1" - "@types/fs-extra" "^9.0.1" - "@vendure/common" "^2.0.6" - apollo-server-express "3.6.3" - bcrypt "^5.1.0" - body-parser "^1.19.0" - chalk "^4.1.0" - commander "^7.1.0" - cookie-session "^2.0.0-rc.1" - csv-parse "^4.12.0" - express "^4.17.1" - fs-extra "^10.0.0" - graphql "16.6.0" - graphql-fields "^2.0.3" - graphql-scalars "^1.20.1" - graphql-tag "^2.12.6" - graphql-upload "^16.0.2" - http-proxy-middleware "^2.0.1" - i18next "^23.2.6" - i18next-fs-backend "^2.1.5" - i18next-http-middleware "^3.3.2" - i18next-icu "^2.3.0" - image-size "^1.0.0" - intl-messageformat "^10.5.0" - mime-types "^2.1.27" - ms "^2.1.2" - nanoid "^3.1.23" - progress "^2.0.3" - reflect-metadata "^0.1.13" - rxjs "^7.5.4" - typeorm "0.3.11" - "@vendure/email-plugin@2.0.4": version "2.0.4" resolved "https://registry.yarnpkg.com/@vendure/email-plugin/-/email-plugin-2.0.4.tgz#7b32c136039b0409e1945ec5fcfc6c1430ee85e2" @@ -5418,21 +5101,6 @@ node-fetch "^2.6.0" sql.js "1.8.0" -"@vendure/testing@2.0.6": - version "2.0.6" - resolved "https://registry.yarnpkg.com/@vendure/testing/-/testing-2.0.6.tgz#60071b2cf484f71fbc80a0292846b010e054c882" - integrity sha512-RQWUVGF/PxnW0BVHNpbKfEPQOYFvN65cM3u/H69Z92XWAH3hi90AAzuVGMxJxRdT01a4165OrQtJ4YUyKZhL0w== - dependencies: - "@graphql-typed-document-node/core" "^3.2.0" - "@types/node-fetch" "^2.5.4" - "@vendure/common" "^2.0.6" - faker "^4.1.0" - form-data "^3.0.0" - graphql "16.6.0" - graphql-tag "^2.10.1" - node-fetch "^2.6.0" - sql.js "1.8.0" - "@vendure/ui-devkit@2.0.4": version "2.0.4" resolved "https://registry.yarnpkg.com/@vendure/ui-devkit/-/ui-devkit-2.0.4.tgz#37a5cd45c8e845aea1d4a89a56d67fdb5049778d" @@ -5450,23 +5118,6 @@ glob "^9.2.1" rxjs "^7.5.4" -"@vendure/ui-devkit@2.0.6": - version "2.0.6" - resolved "https://registry.yarnpkg.com/@vendure/ui-devkit/-/ui-devkit-2.0.6.tgz#b4463d198597e237efbac0e6bd80d1e68a830c7a" - integrity sha512-CRQeox2W3snRRIA4z94M72fiZnt91jS+fc6woKBbem20DEUmDC2F7XEWjwED+jaGTkGbpON5f0wW5kj09GvQKw== - dependencies: - "@angular-devkit/build-angular" "^16.0.3" - "@angular/cli" "^16.0.3" - "@angular/compiler" "^16.0.3" - "@angular/compiler-cli" "^16.0.3" - "@vendure/admin-ui" "^2.0.6" - "@vendure/common" "^2.0.6" - chalk "^4.1.0" - chokidar "^3.5.1" - fs-extra "^10.0.0" - glob "^9.2.1" - rxjs "^7.5.4" - "@vitejs/plugin-basic-ssl@1.0.1": version "1.0.1" resolved "https://registry.yarnpkg.com/@vitejs/plugin-basic-ssl/-/plugin-basic-ssl-1.0.1.tgz#48c46eab21e0730921986ce742563ae83fe7fe34" @@ -5773,27 +5424,11 @@ resolved "https://registry.yarnpkg.com/@webcomponents/webcomponentsjs/-/webcomponentsjs-2.8.0.tgz#ab21f027594fa827c1889e8b646da7be27c7908a" integrity sha512-loGD63sacRzOzSJgQnB9ZAhaQGkN7wl2Zuw7tsphI5Isa0irijrRo6EnJii/GgjGefIFO8AIO7UivzRhFaEk9w== -"@whatwg-node/events@^0.0.2": - version "0.0.2" - resolved "https://registry.yarnpkg.com/@whatwg-node/events/-/events-0.0.2.tgz#7b7107268d2982fc7b7aff5ee6803c64018f84dd" - integrity sha512-WKj/lI4QjnLuPrim0cfO7i+HsDSXHxNv1y0CrJhdntuO3hxWZmnXCwNDnwOvry11OjRin6cgWNF+j/9Pn8TN4w== - "@whatwg-node/events@^0.0.3": version "0.0.3" resolved "https://registry.yarnpkg.com/@whatwg-node/events/-/events-0.0.3.tgz#13a65dd4f5893f55280f766e29ae48074927acad" integrity sha512-IqnKIDWfXBJkvy/k6tzskWTc2NK3LcqHlb+KHGCrjOCH4jfQckRX0NAiIcC/vIqQkzLYw2r2CTSwAxcrtcD6lA== -"@whatwg-node/fetch@^0.6.0": - version "0.6.9" - resolved "https://registry.yarnpkg.com/@whatwg-node/fetch/-/fetch-0.6.9.tgz#6cc694cc0378e27b8dfed427c5bf633eda6972b9" - integrity sha512-JfrBCJdMu9n9OARc0e/hPHcD98/8Nz1CKSdGYDg6VbObDkV/Ys30xe5i/wPOatYbxuvatj1kfWeHf7iNX3i17w== - dependencies: - "@peculiar/webcrypto" "^1.4.0" - "@whatwg-node/node-fetch" "^0.0.5" - busboy "^1.6.0" - urlpattern-polyfill "^6.0.2" - web-streams-polyfill "^3.2.1" - "@whatwg-node/fetch@^0.8.0", "@whatwg-node/fetch@^0.8.1", "@whatwg-node/fetch@^0.8.2": version "0.8.8" resolved "https://registry.yarnpkg.com/@whatwg-node/fetch/-/fetch-0.8.8.tgz#48c6ad0c6b7951a73e812f09dd22d75e9fa18cae" @@ -5805,15 +5440,6 @@ urlpattern-polyfill "^8.0.0" web-streams-polyfill "^3.2.1" -"@whatwg-node/node-fetch@^0.0.5": - version "0.0.5" - resolved "https://registry.yarnpkg.com/@whatwg-node/node-fetch/-/node-fetch-0.0.5.tgz#bebf18891088e5e2fc449dea8d1bc94af5ec38df" - integrity sha512-hbccmaSZaItdsRuBKBEEhLoO+5oXJPxiyd0kG2xXd0Dh3Rt+vZn4pADHxuSiSHLd9CM+S2z4+IxlEGbWUgiz9g== - dependencies: - "@whatwg-node/events" "^0.0.2" - busboy "^1.6.0" - tslib "^2.3.1" - "@whatwg-node/node-fetch@^0.3.6": version "0.3.6" resolved "https://registry.yarnpkg.com/@whatwg-node/node-fetch/-/node-fetch-0.3.6.tgz#e28816955f359916e2d830b68a64493124faa6d0" @@ -6066,7 +5692,7 @@ ansi-escapes@^3.0.0: resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.2.0.tgz#8780b98ff9dbf5638152d1f1fe5c1d7b4442976b" integrity sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ== -ansi-escapes@^4.2.1, ansi-escapes@^4.3.0, ansi-escapes@^4.3.1: +ansi-escapes@^4.2.1, ansi-escapes@^4.3.1: version "4.3.2" resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e" integrity sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ== @@ -6392,11 +6018,6 @@ assertion-error@^1.1.0: resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.1.0.tgz#e60b6b0e8f301bd97e5375215bda406c85118c0b" integrity sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw== -astral-regex@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-2.0.0.tgz#483143c567aeed4785759c0865786dc77d7d2e31" - integrity sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ== - async-retry@^1.2.1, async-retry@^1.3.3: version "1.3.3" resolved "https://registry.yarnpkg.com/async-retry/-/async-retry-1.3.3.tgz#0e7f36c04d8478e7a58bdbed80cedf977785f280" @@ -7241,14 +6862,6 @@ cli-truncate@^0.2.1: slice-ansi "0.0.4" string-width "^1.0.1" -cli-truncate@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/cli-truncate/-/cli-truncate-2.1.0.tgz#c39e28bf05edcde5be3b98992a22deed5a2b93c7" - integrity sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg== - dependencies: - slice-ansi "^3.0.0" - string-width "^4.2.0" - cli-width@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-3.0.0.tgz#a2f48437a2caa9a22436e794bf071ec9e61cedf6" @@ -7369,7 +6982,7 @@ color@^4.2.3: color-convert "^2.0.1" color-string "^1.9.0" -colorette@^2.0.10, colorette@^2.0.16: +colorette@^2.0.10: version "2.0.20" resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.20.tgz#9eb793e6833067f7235902fcd3b09917a000a95a" integrity sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w== @@ -7705,7 +7318,7 @@ copy-webpack-plugin@11.0.0: schema-utils "^4.0.0" serialize-javascript "^6.0.0" -copyfiles@2.4.1, copyfiles@^2.4.1: +copyfiles@2.4.1: version "2.4.1" resolved "https://registry.yarnpkg.com/copyfiles/-/copyfiles-2.4.1.tgz#d2dcff60aaad1015f09d0b66e7f0f1c5cd3c5da5" integrity sha512-fereAvAvxDrQDOXybk3Qu3dPbOoKoysFMWtkY3mv5BsL8//OSZVL5DCLYqgRfY5cWirgRzlC+WSrxp6Bo3eNZg== @@ -7748,7 +7361,7 @@ cors@2.8.5, cors@^2.8.5: object-assign "^4" vary "^1" -cosmiconfig-typescript-loader@^4.0.0, cosmiconfig-typescript-loader@^4.3.0: +cosmiconfig-typescript-loader@^4.0.0: version "4.4.0" resolved "https://registry.yarnpkg.com/cosmiconfig-typescript-loader/-/cosmiconfig-typescript-loader-4.4.0.tgz#f3feae459ea090f131df5474ce4b1222912319f9" integrity sha512-BabizFdC3wBHhbI4kJh0VkQP9GkBfoHPydD0COMce1nJ1kJAB3F2TmJ/I7diULBKtmEWSwEbuN/KDtgnmUUVmw== @@ -9895,7 +9508,7 @@ graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6 resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== -graphql-config@^4.1.0, graphql-config@^4.4.0: +graphql-config@^4.1.0: version "4.5.0" resolved "https://registry.yarnpkg.com/graphql-config/-/graphql-config-4.5.0.tgz#257c2338950b8dce295a27f75c5f6c39f8f777b2" integrity sha512-x6D0/cftpLUJ0Ch1e5sj1TZn6Wcxx4oMfmhaG9shM0DKajA9iR+j1z86GSTQ19fShbGvrSSvbIQsHku6aQ6BBw== @@ -11607,20 +11220,6 @@ listr-verbose-renderer@^0.5.0: date-fns "^1.27.2" figures "^2.0.0" -listr2@^4.0.5: - version "4.0.5" - resolved "https://registry.yarnpkg.com/listr2/-/listr2-4.0.5.tgz#9dcc50221583e8b4c71c43f9c7dfd0ef546b75d5" - integrity sha512-juGHV1doQdpNT3GSTs9IUN43QJb7KHdF9uqg7Vufs/tG9VTzpFphqF4pm/ICdAABGQxsyNn9CiYA3StkI6jpwA== - dependencies: - cli-truncate "^2.1.0" - colorette "^2.0.16" - log-update "^4.0.0" - p-map "^4.0.0" - rfdc "^1.3.0" - rxjs "^7.5.5" - through "^2.3.8" - wrap-ansi "^7.0.0" - listr@^0.14.3: version "0.14.3" resolved "https://registry.yarnpkg.com/listr/-/listr-0.14.3.tgz#2fea909604e434be464c50bddba0d496928fa586" @@ -11838,16 +11437,6 @@ log-update@^2.3.0: cli-cursor "^2.0.0" wrap-ansi "^3.0.1" -log-update@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/log-update/-/log-update-4.0.0.tgz#589ecd352471f2a1c0c570287543a64dfd20e0a1" - integrity sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg== - dependencies: - ansi-escapes "^4.3.0" - cli-cursor "^3.1.0" - slice-ansi "^4.0.0" - wrap-ansi "^6.2.0" - loglevel@^1.6.8: version "1.8.1" resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.8.1.tgz#5c621f83d5b48c54ae93b6156353f555963377b4" @@ -12930,16 +12519,6 @@ no-case@^3.0.4: lower-case "^2.0.2" tslib "^2.0.3" -nock@*, nock@^13.2.9: - version "13.3.2" - resolved "https://registry.yarnpkg.com/nock/-/nock-13.3.2.tgz#bfa6be92d37f744b1b758ea89b1105cdaf5c8b3f" - integrity sha512-CwbljitiWJhF1gL83NbanhoKs1l23TDlRioNraPTZrzZIEooPemrHRj5m0FZCPkB1ecdYCSWWGcHysJgX/ngnQ== - dependencies: - debug "^4.1.0" - json-stringify-safe "^5.0.1" - lodash "^4.17.21" - propagate "^2.0.0" - nock@13.2.4: version "13.2.4" resolved "https://registry.yarnpkg.com/nock/-/nock-13.2.4.tgz#43a309d93143ee5cdcca91358614e7bde56d20e1" @@ -12984,7 +12563,7 @@ node-emoji@1.11.0: dependencies: lodash "^4.17.21" -node-fetch@2, node-fetch@^2.0.0, node-fetch@^2.6.0, node-fetch@^2.6.1, node-fetch@^2.6.12, node-fetch@^2.6.9: +node-fetch@2, node-fetch@^2.6.0, node-fetch@^2.6.1, node-fetch@^2.6.12, node-fetch@^2.6.9: version "2.6.12" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.12.tgz#02eb8e22074018e3d5a83016649d04df0e348fba" integrity sha512-C/fGU2E8ToujUivIO0H+tpQ6HWo4eEmchoPIoXtxCrVghxdKq+QOHqEZW7tuP3KlV3bC8FRMO5nMCC7Zm1VP6g== @@ -15091,11 +14670,6 @@ reusify@^1.0.4: resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== -rfdc@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.3.0.tgz#d0b7c441ab2720d05dc4cf26e01c89631d9da08b" - integrity sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA== - rimraf@3.0.2, rimraf@^3.0.0, rimraf@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" @@ -15541,24 +15115,6 @@ slice-ansi@0.0.4: resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-0.0.4.tgz#edbf8903f66f7ce2f8eafd6ceed65e264c831b35" integrity sha512-up04hB2hR92PgjpyU3y/eg91yIBILyjVY26NvvciY3EVVPjybkMszMpXQ9QAkcS3I5rtJBDLoTxxg+qvW8c7rw== -slice-ansi@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-3.0.0.tgz#31ddc10930a1b7e0b67b08c96c2f49b77a789787" - integrity sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ== - dependencies: - ansi-styles "^4.0.0" - astral-regex "^2.0.0" - is-fullwidth-code-point "^3.0.0" - -slice-ansi@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-4.0.0.tgz#500e8dd0fd55b05815086255b3195adf2a45fe6b" - integrity sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ== - dependencies: - ansi-styles "^4.0.0" - astral-regex "^2.0.0" - is-fullwidth-code-point "^3.0.0" - slick@^1.12.2: version "1.12.2" resolved "https://registry.yarnpkg.com/slick/-/slick-1.12.2.tgz#bd048ddb74de7d1ca6915faa4a57570b3550c2d7" @@ -16260,7 +15816,7 @@ through2@^4.0.0: dependencies: readable-stream "3" -through@2, "through@>=2.2.7 <3", through@^2.3.4, through@^2.3.6, through@^2.3.8: +through@2, "through@>=2.2.7 <3", through@^2.3.4, through@^2.3.6: version "2.3.8" resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" integrity sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg== @@ -16484,7 +16040,7 @@ tslib@2.5.0, tslib@^2.1.0, tslib@^2.3.0, tslib@^2.4.0: resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.5.0.tgz#42bfed86f5787aeb41d031866c8f402429e0fddf" integrity sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg== -tslib@2.5.3, tslib@~2.5.0: +tslib@2.5.3: version "2.5.3" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.5.3.tgz#24944ba2d990940e6e982c4bea147aba80209913" integrity sha512-mSxlJJwl3BMEQCUNnxXBU9jP4JBktcEGhURcPR6VQVlnP0FdDEsIaz0C35dXNGLyRfrATNofF0F5p2KPxQgB+w== @@ -16800,7 +16356,7 @@ unpipe@1.0.0, unpipe@~1.0.0: resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== -unplugin-swc@1.3.2, unplugin-swc@^1.3.2: +unplugin-swc@1.3.2: version "1.3.2" resolved "https://registry.yarnpkg.com/unplugin-swc/-/unplugin-swc-1.3.2.tgz#4c859896ce33a46f66033ba66290b33fb886a248" integrity sha512-x0+NTM4NR1jWpailVhK5sXO9svyL4iWZ+yah0WZ1G+SaI1hPysa95nVSzXqLP7y4+MKTO17wP+EVqjrREqgBsw== @@ -16895,13 +16451,6 @@ url@0.10.3: punycode "1.3.2" querystring "0.2.0" -urlpattern-polyfill@^6.0.2: - version "6.0.2" - resolved "https://registry.yarnpkg.com/urlpattern-polyfill/-/urlpattern-polyfill-6.0.2.tgz#a193fe773459865a2a5c93b246bb794b13d07256" - integrity sha512-5vZjFlH9ofROmuWmXM9yj2wljYKgWstGwe8YTyiqM7hVum/g9LyCizPZtb3UqsuppVwety9QJmfc42VggLpTgg== - dependencies: - braces "^3.0.2" - urlpattern-polyfill@^8.0.0: version "8.0.2" resolved "https://registry.yarnpkg.com/urlpattern-polyfill/-/urlpattern-polyfill-8.0.2.tgz#99f096e35eff8bf4b5a2aa7d58a1523d6ebc7ce5" @@ -17049,7 +16598,7 @@ vite@4.3.9: optionalDependencies: fsevents "~2.3.2" -vitest@0.30.1, vitest@^0.30.1: +vitest@0.30.1: version "0.30.1" resolved "https://registry.yarnpkg.com/vitest/-/vitest-0.30.1.tgz#351d4a2f27aa8cc0245e3583e3ed45e30efc71d6" integrity sha512-y35WTrSTlTxfMLttgQk4rHcaDkbHQwDP++SNwPb+7H8yb13Q3cu2EixrtHzF27iZ8v0XCciSsLg00RkPAzB/aA== From 14dd47321113b25b6b0fb68f0cc7d4f36d1bbd9f Mon Sep 17 00:00:00 2001 From: Martijn Date: Wed, 16 Aug 2023 09:01:00 +0200 Subject: [PATCH 10/11] fix(stripe-subscription): increased version number --- packages/vendure-plugin-stripe-subscription/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/vendure-plugin-stripe-subscription/package.json b/packages/vendure-plugin-stripe-subscription/package.json index b435a5c8..a1de9cf8 100644 --- a/packages/vendure-plugin-stripe-subscription/package.json +++ b/packages/vendure-plugin-stripe-subscription/package.json @@ -1,6 +1,6 @@ { "name": "@pinelab/vendure-plugin-stripe-subscription", - "version": "1.2.1", + "version": "1.2.0", "description": "Vendure plugin for selling subscriptions via Stripe", "author": "Martijn van de Brug ", "homepage": "https://pinelab-plugins.com/", From 9101619ef0069f37ac252cb2a1bdb6331e917223 Mon Sep 17 00:00:00 2001 From: Martijn Date: Wed, 16 Aug 2023 09:30:36 +0200 Subject: [PATCH 11/11] fix(stripe-subscription): styling and cleanup of unused components --- .../schedules.component-2.html | 333 ----------- .../schedules.component-2.ts | 324 ---------- .../schedules.component.html | 559 +++++++++++------- .../schedules.component.ts | 145 +++-- .../src/ui/stripe-subscription.module.ts | 5 +- 5 files changed, 456 insertions(+), 910 deletions(-) delete mode 100644 packages/vendure-plugin-stripe-subscription/src/ui/schedules-component/schedules.component-2.html delete mode 100644 packages/vendure-plugin-stripe-subscription/src/ui/schedules-component/schedules.component-2.ts diff --git a/packages/vendure-plugin-stripe-subscription/src/ui/schedules-component/schedules.component-2.html b/packages/vendure-plugin-stripe-subscription/src/ui/schedules-component/schedules.component-2.html deleted file mode 100644 index 205ab590..00000000 --- a/packages/vendure-plugin-stripe-subscription/src/ui/schedules-component/schedules.component-2.html +++ /dev/null @@ -1,333 +0,0 @@ - - - -

Stripe Subscription Schedules

-

- Manage subscription schedules here. A schedule can be connected to a - product variant to make it a subscription. -

-
- - - -
-
- - - - - - - {{ schedule.id }} - - - - {{ schedule.createdAt | localeDate : 'short' }} - - - - - {{ schedule.updatedAt | localeDate : 'short' }} - - - - - - {{ schedule.name }} - - - - - - {{ schedule.downpayment | localeCurrency }} - - - - - {{ schedule.durationInterval }} - - - - - {{ schedule.durationCount }} - - - - - {{ schedule.startMoment }} - - - - - {{ schedule.billingInterval }} - - - - - {{ schedule.billingCount }} - - - - - {{ schedule.paidUpFront }} - - - - - {{ schedule.fixedStartDate | localeDate : 'short'}} - - - - - {{ schedule.useProration }} - - - - - {{ schedule.autoRenew }} - - - - - - -
-
-
- - - - - - - - - - - - - - - - every - - - - - - - - - - of the {{ form.value.isPaidUpFront ? - form.value.durationInterval : form.value.billingInterval - }} - - - - - - - - - - - - - - - - - - - - - - - -
-
-
-
-
-
diff --git a/packages/vendure-plugin-stripe-subscription/src/ui/schedules-component/schedules.component-2.ts b/packages/vendure-plugin-stripe-subscription/src/ui/schedules-component/schedules.component-2.ts deleted file mode 100644 index 4c32f848..00000000 --- a/packages/vendure-plugin-stripe-subscription/src/ui/schedules-component/schedules.component-2.ts +++ /dev/null @@ -1,324 +0,0 @@ -import { ChangeDetectorRef, Component, OnInit } from '@angular/core'; -import { FormBuilder, FormGroup, Validators } from '@angular/forms'; -import { - DataService, - ModalService, - NotificationService, -} from '@vendure/admin-ui/core'; -import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; -import { DELETE_SCHEDULE, GET_SCHEDULES, UPSERT_SCHEDULES } from '../queries'; -import { - StripeSubscriptionSchedule, - StripeSubscriptionSchedulesDocument, - SubscriptionInterval, - SubscriptionStartMoment, -} from '../generated/graphql'; -import { TypedBaseListComponent } from '@vendure/admin-ui/core'; - -@Component({ - selector: 'stripe-subscription-component-2', - styleUrls: ['./schedules.component.scss'], - templateUrl: './schedules.component-2.html', -}) -export class SchedulesComponent - extends TypedBaseListComponent< - typeof StripeSubscriptionSchedulesDocument, - 'stripeSubscriptionSchedules' - > - implements OnInit -{ - readonly filters: any = ( - this.createFilterCollection().addDateFilters() as any - ) - .addFilters([ - { - name: 'id', - type: { kind: 'text' }, - label: _('common.id'), - filterField: 'id', - }, - ]) - .connectToRoute(this.route); - readonly sorts: any = this.createSortCollection() - .defaultSort('createdAt', 'DESC') - .addSorts([ - { name: 'id' }, - { name: 'createdAt' }, - { name: 'updatedAt' }, - { name: 'name' }, - { name: 'downpayment' }, - { name: 'durationInterval' }, - { name: 'durationCount' }, - { name: 'startMoment' }, - { name: 'billingInterval' }, - { name: 'billingCount' }, - { name: 'paidUpFront' }, - { name: 'fixedStartDate' }, - { name: 'useProration' }, - { name: 'autoRenew' }, - ]) - .connectToRoute(this.route); - schedules: StripeSubscriptionSchedule[] = []; - selectedSchedule?: StripeSubscriptionSchedule; - page = 1; - itemsPerPage = 10; - form: FormGroup; - currencyCode!: string; - intervals = [SubscriptionInterval.Week, SubscriptionInterval.Month]; - moments = [ - { - name: 'First', - value: SubscriptionStartMoment.StartOfBillingInterval, - }, - { - name: 'Last', - value: SubscriptionStartMoment.EndOfBillingInterval, - }, - { - name: 'Time of purchase', - value: SubscriptionStartMoment.TimeOfPurchase, - }, - { - name: 'Fixed date', - value: SubscriptionStartMoment.FixedStartdate, - }, - ]; - - constructor( - private formBuilder: FormBuilder, - protected dataService: DataService, - private changeDetector: ChangeDetectorRef, - private notificationService: NotificationService, - private modalService: ModalService - ) { - super(); - this.form = this.formBuilder.group({ - name: ['name', Validators.required], - isPaidUpFront: [false], - downpayment: [0, Validators.required], - durationInterval: ['durationInterval', Validators.required], - durationCount: ['durationCount', Validators.required], - startMoment: ['startMoment', Validators.required], - billingInterval: ['billingInterval', Validators.required], - billingCount: ['billingCount', Validators.required], - fixedStartDate: ['fixedStartDate'], - useProration: [false], - autoRenew: [true], - }); - this.configure({ - document: StripeSubscriptionSchedulesDocument, - getItems: (data) => data.stripeSubscriptionSchedules, - setVariables: (skip, take) => - ({ - options: { - skip, - take, - filter: { - name: { - contains: this.searchTermControl.value, - }, - ...this.filters.createFilterInput(), - }, - sort: this.sorts.createSortInput() as any, - }, - } as any), - refreshListOnChanges: [ - this.sorts.valueChanges, - this.filters.valueChanges, - ], - }); - } - get now() { - return new Date().toISOString(); - } - - closeDetail() { - this.selectedSchedule = undefined; - } - - async ngOnInit(): Promise { - // await this.fetchSchedules(); - super.ngOnInit(); - this.dataService.settings.getActiveChannel().single$.subscribe((data) => { - this.currencyCode = data.activeChannel.defaultCurrencyCode; - }); - } - - selectDurationInterval(interval: 'week' | 'month') { - this.form.controls['durationInterval'].setValue(interval); - } - - selectBillingInterval(interval: 'week' | 'month') { - this.form.controls['billingInterval'].setValue(interval); - } - - edit(scheduleId: string): void { - this.items$.subscribe((schedules) => { - this.selectedSchedule = schedules.find((s) => s.id === scheduleId) as any; - if (!this.selectedSchedule) { - return; - } - this.form.controls['name'].setValue(this.selectedSchedule.name); - this.form.controls['downpayment'].setValue( - this.selectedSchedule.downpayment - ); - this.form.controls['durationInterval'].setValue( - this.selectedSchedule.durationInterval - ); - this.form.controls['durationCount'].setValue( - this.selectedSchedule.durationCount - ); - this.form.controls['startMoment'].setValue( - this.selectedSchedule.startMoment - ); - this.form.controls['billingInterval'].setValue( - this.selectedSchedule.billingInterval - ); - this.form.controls['billingCount'].setValue( - this.selectedSchedule.billingCount - ); - this.form.controls['isPaidUpFront'].setValue( - this.selectedSchedule.paidUpFront - ); - this.form.controls['fixedStartDate'].setValue( - this.selectedSchedule.fixedStartDate - ); - this.form.controls['useProration'].setValue( - this.selectedSchedule.useProration - ); - this.form.controls['autoRenew'].setValue(this.selectedSchedule.autoRenew); - }); - } - - newSchedule(): void { - this.selectedSchedule = { - name: 'New schedule', - downpayment: 0, - durationInterval: SubscriptionInterval.Month, - durationCount: 6, - startMoment: SubscriptionStartMoment.StartOfBillingInterval, - billingInterval: SubscriptionInterval.Month, - billingCount: 1, - } as StripeSubscriptionSchedule; - this.form.controls['name'].setValue(this.selectedSchedule.name); - this.form.controls['downpayment'].setValue( - this.selectedSchedule.downpayment - ); - this.form.controls['durationInterval'].setValue( - this.selectedSchedule.durationInterval - ); - this.form.controls['durationCount'].setValue( - this.selectedSchedule.durationCount - ); - this.form.controls['startMoment'].setValue( - this.selectedSchedule.startMoment - ); - this.form.controls['billingInterval'].setValue( - this.selectedSchedule.billingInterval - ); - this.form.controls['billingCount'].setValue( - this.selectedSchedule.billingCount - ); - this.form.controls['billingCount'].setValue( - this.selectedSchedule.billingCount - ); - this.form.controls['fixedStartDate'].setValue(undefined); - } - - async save(): Promise { - try { - if (this.form.dirty) { - const formValue = this.form.value; - if (formValue.isPaidUpFront) { - formValue.downpayment = 0; - // For paid up front duration and billing cycles are the same - formValue.billingInterval = formValue.durationInterval; - formValue.billingCount = formValue.durationCount; - } - if (formValue.startMoment === SubscriptionStartMoment.FixedStartdate) { - formValue.useProration = false; - } - await this.dataService - .mutate(UPSERT_SCHEDULES, { - input: { - id: this.selectedSchedule?.id, - name: formValue.name, - downpayment: formValue.downpayment, - durationInterval: formValue.durationInterval, - durationCount: formValue.durationCount, - startMoment: formValue.startMoment, - billingInterval: formValue.billingInterval, - billingCount: formValue.billingCount, - fixedStartDate: formValue.fixedStartDate, - useProration: formValue.useProration, - autoRenew: formValue.autoRenew, - }, - }) - .toPromise(); - } - this.form.markAsPristine(); - this.changeDetector.markForCheck(); - this.notificationService.success('common.notify-update-success', { - entity: 'Schedule', - }); - } catch (e) { - this.notificationService.error('common.notify-update-error', { - entity: 'Schedule', - }); - } finally { - super.ngOnInit(); - this.selectedSchedule = undefined; - } - } - - deleteSchedule(scheduleId: string): void { - this.modalService - .dialog({ - title: 'Are you sure you want to delete this schedule?', - buttons: [ - { type: 'secondary', label: 'Cancel' }, - { type: 'danger', label: 'Delete', returnValue: true }, - ], - }) - .subscribe(async (confirm) => { - if (confirm) { - await this.dataService - .mutate(DELETE_SCHEDULE, { scheduleId }) - .toPromise(); - this.notificationService.success('Deleted schedule', { - entity: 'Product', - }); - this.selectedSchedule = undefined; - await this.fetchSchedules(); - } - }); - } - - closeEdit() { - this.selectedSchedule = undefined; - } - - async fetchSchedules(): Promise { - this.dataService - .query(GET_SCHEDULES) - .refetchOnChannelChange() - .mapStream((result: any) => result.stripeSubscriptionSchedules) - .subscribe((schedules) => { - this.schedules = schedules.slice( - (this.page - 1) * this.itemsPerPage, - this.itemsPerPage - ); - }); - } - - async setPageNumber(page: number) { - this.page = page; - await this.fetchSchedules(); - } - - async setItemsPerPage(nrOfItems: number) { - this.page = 1; - this.itemsPerPage = Number(nrOfItems); - await this.fetchSchedules(); - } -} diff --git a/packages/vendure-plugin-stripe-subscription/src/ui/schedules-component/schedules.component.html b/packages/vendure-plugin-stripe-subscription/src/ui/schedules-component/schedules.component.html index e85a9f92..f1c6dc2a 100644 --- a/packages/vendure-plugin-stripe-subscription/src/ui/schedules-component/schedules.component.html +++ b/packages/vendure-plugin-stripe-subscription/src/ui/schedules-component/schedules.component.html @@ -1,214 +1,347 @@ -

Stripe Subscription Schedules

-

- Manage subscription schedules here. A schedule can be connected to a product - variant to make it a subscription. -

-
- -
- - - {{ schedule.id }} - {{ schedule.name }} - - {{ schedule.createdAt | date }} - - - - - - - - - -
-
-
-

- {{ - selectedSchedule?.id - ? 'Edit schedule ' + selectedSchedule?.id - : 'Create new schedule' - }} -

- -
-
- -
-
- - - - - - - - - - - - - - - - every - - - - - - - - - - of the - {{ - form.value.isPaidUpFront - ? form.value.durationInterval - : form.value.billingInterval - }} + + +

Stripe Subscription Schedules

+

+ Manage subscription schedules here. A schedule can be connected to a + product variant to make it a subscription. +

+
+ + + +
+ + + + + + + + {{ schedule.id }} + + + + {{ schedule.createdAt | localeDate : 'short' }} + + + + + {{ schedule.updatedAt | localeDate : 'short' }} + + + + + + {{ schedule.name }} + + + + + + {{ schedule.downpayment | localeCurrency }} + + + + + {{ schedule.durationInterval }} + + + + + {{ schedule.durationCount }} + + + + + {{ schedule.startMoment }} + + + + + {{ schedule.billingInterval }} + + + + + {{ schedule.billingCount }} + + + + + {{ schedule.paidUpFront }} + + + + + {{ schedule.fixedStartDate | localeDate : 'short' }} + + + + + {{ schedule.useProration }} + + + + + {{ schedule.autoRenew }} + + + + + + +
+ +
+ + + + + + + + + + + + + + + + every + + + + + + + + + + of the + {{ + form.value.isPaidUpFront + ? form.value.durationInterval + : form.value.billingInterval + }} + + + + - - - - - - - - - - - - - - - - - - - - - - - -
- -
-
+ + + + + + + + + + + + + + + + + + + + + +
+ + + diff --git a/packages/vendure-plugin-stripe-subscription/src/ui/schedules-component/schedules.component.ts b/packages/vendure-plugin-stripe-subscription/src/ui/schedules-component/schedules.component.ts index 32f48985..9ebcc2b3 100644 --- a/packages/vendure-plugin-stripe-subscription/src/ui/schedules-component/schedules.component.ts +++ b/packages/vendure-plugin-stripe-subscription/src/ui/schedules-component/schedules.component.ts @@ -5,19 +5,59 @@ import { ModalService, NotificationService, } from '@vendure/admin-ui/core'; +import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; import { DELETE_SCHEDULE, GET_SCHEDULES, UPSERT_SCHEDULES } from '../queries'; import { StripeSubscriptionSchedule, + StripeSubscriptionSchedulesDocument, SubscriptionInterval, SubscriptionStartMoment, } from '../generated/graphql'; +import { TypedBaseListComponent } from '@vendure/admin-ui/core'; @Component({ selector: 'stripe-subscription-component', styleUrls: ['./schedules.component.scss'], templateUrl: './schedules.component.html', }) -export class SchedulesComponent implements OnInit { +export class SchedulesComponent + extends TypedBaseListComponent< + typeof StripeSubscriptionSchedulesDocument, + 'stripeSubscriptionSchedules' + > + implements OnInit +{ + readonly filters: any = ( + this.createFilterCollection().addDateFilters() as any + ) + .addFilters([ + { + name: 'id', + type: { kind: 'text' }, + label: _('common.id'), + filterField: 'id', + }, + ]) + .connectToRoute(this.route); + readonly sorts: any = this.createSortCollection() + .defaultSort('createdAt', 'DESC') + .addSorts([ + { name: 'id' }, + { name: 'createdAt' }, + { name: 'updatedAt' }, + { name: 'name' }, + { name: 'downpayment' }, + { name: 'durationInterval' }, + { name: 'durationCount' }, + { name: 'startMoment' }, + { name: 'billingInterval' }, + { name: 'billingCount' }, + { name: 'paidUpFront' }, + { name: 'fixedStartDate' }, + { name: 'useProration' }, + { name: 'autoRenew' }, + ]) + .connectToRoute(this.route); schedules: StripeSubscriptionSchedule[] = []; selectedSchedule?: StripeSubscriptionSchedule; page = 1; @@ -51,6 +91,7 @@ export class SchedulesComponent implements OnInit { private notificationService: NotificationService, private modalService: ModalService ) { + super(); this.form = this.formBuilder.group({ name: ['name', Validators.required], isPaidUpFront: [false], @@ -64,13 +105,40 @@ export class SchedulesComponent implements OnInit { useProration: [false], autoRenew: [true], }); + this.configure({ + document: StripeSubscriptionSchedulesDocument, + getItems: (data) => data.stripeSubscriptionSchedules, + setVariables: (skip, take) => + ({ + options: { + skip, + take, + filter: { + name: { + contains: this.searchTermControl.value, + }, + ...this.filters.createFilterInput(), + }, + sort: this.sorts.createSortInput() as any, + }, + } as any), + refreshListOnChanges: [ + this.sorts.valueChanges, + this.filters.valueChanges, + ], + }); } get now() { return new Date().toISOString(); } + closeDetail() { + this.selectedSchedule = undefined; + } + async ngOnInit(): Promise { - await this.fetchSchedules(); + // await this.fetchSchedules(); + super.ngOnInit(); this.dataService.settings.getActiveChannel().single$.subscribe((data) => { this.currencyCode = data.activeChannel.defaultCurrencyCode; }); @@ -85,39 +153,41 @@ export class SchedulesComponent implements OnInit { } edit(scheduleId: string): void { - this.selectedSchedule = this.schedules.find((s) => s.id === scheduleId); - if (!this.selectedSchedule) { - return; - } - this.form.controls['name'].setValue(this.selectedSchedule.name); - this.form.controls['downpayment'].setValue( - this.selectedSchedule.downpayment - ); - this.form.controls['durationInterval'].setValue( - this.selectedSchedule.durationInterval - ); - this.form.controls['durationCount'].setValue( - this.selectedSchedule.durationCount - ); - this.form.controls['startMoment'].setValue( - this.selectedSchedule.startMoment - ); - this.form.controls['billingInterval'].setValue( - this.selectedSchedule.billingInterval - ); - this.form.controls['billingCount'].setValue( - this.selectedSchedule.billingCount - ); - this.form.controls['isPaidUpFront'].setValue( - this.selectedSchedule.paidUpFront - ); - this.form.controls['fixedStartDate'].setValue( - this.selectedSchedule.fixedStartDate - ); - this.form.controls['useProration'].setValue( - this.selectedSchedule.useProration - ); - this.form.controls['autoRenew'].setValue(this.selectedSchedule.autoRenew); + this.items$.subscribe((schedules) => { + this.selectedSchedule = schedules.find((s) => s.id === scheduleId) as any; + if (!this.selectedSchedule) { + return; + } + this.form.controls['name'].setValue(this.selectedSchedule.name); + this.form.controls['downpayment'].setValue( + this.selectedSchedule.downpayment + ); + this.form.controls['durationInterval'].setValue( + this.selectedSchedule.durationInterval + ); + this.form.controls['durationCount'].setValue( + this.selectedSchedule.durationCount + ); + this.form.controls['startMoment'].setValue( + this.selectedSchedule.startMoment + ); + this.form.controls['billingInterval'].setValue( + this.selectedSchedule.billingInterval + ); + this.form.controls['billingCount'].setValue( + this.selectedSchedule.billingCount + ); + this.form.controls['isPaidUpFront'].setValue( + this.selectedSchedule.paidUpFront + ); + this.form.controls['fixedStartDate'].setValue( + this.selectedSchedule.fixedStartDate + ); + this.form.controls['useProration'].setValue( + this.selectedSchedule.useProration + ); + this.form.controls['autoRenew'].setValue(this.selectedSchedule.autoRenew); + }); } newSchedule(): void { @@ -196,7 +266,8 @@ export class SchedulesComponent implements OnInit { entity: 'Schedule', }); } finally { - await this.fetchSchedules(); + super.ngOnInit(); + this.selectedSchedule = undefined; } } @@ -233,7 +304,7 @@ export class SchedulesComponent implements OnInit { .refetchOnChannelChange() .mapStream((result: any) => result.stripeSubscriptionSchedules) .subscribe((schedules) => { - this.schedules = schedules.items.slice( + this.schedules = schedules.slice( (this.page - 1) * this.itemsPerPage, this.itemsPerPage ); diff --git a/packages/vendure-plugin-stripe-subscription/src/ui/stripe-subscription.module.ts b/packages/vendure-plugin-stripe-subscription/src/ui/stripe-subscription.module.ts index bf2e1ffa..50eccf1d 100644 --- a/packages/vendure-plugin-stripe-subscription/src/ui/stripe-subscription.module.ts +++ b/packages/vendure-plugin-stripe-subscription/src/ui/stripe-subscription.module.ts @@ -3,7 +3,6 @@ import { RouterModule } from '@angular/router'; import { SharedModule } from '@vendure/admin-ui/core'; import { SchedulesComponent } from './schedules-component/schedules.component'; import { PaymentsComponent } from './payments-component/payments.component'; -import { SchedulesComponent as Schedules2Component } from './schedules-component/schedules.component-2'; @NgModule({ imports: [ @@ -11,7 +10,7 @@ import { SchedulesComponent as Schedules2Component } from './schedules-component RouterModule.forChild([ { path: 'subscription-schedules', - component: Schedules2Component, + component: SchedulesComponent, data: { breadcrumb: 'Subscription schedules' }, }, { @@ -22,6 +21,6 @@ import { SchedulesComponent as Schedules2Component } from './schedules-component ]), ], providers: [], - declarations: [SchedulesComponent, PaymentsComponent, Schedules2Component], + declarations: [SchedulesComponent, PaymentsComponent], }) export class SchedulesModule {}