From 2f1fbb8824d8b2f0a2003dca4966ef2de235c2f9 Mon Sep 17 00:00:00 2001 From: vchikalkin Date: Tue, 26 Aug 2025 18:53:50 +0300 Subject: [PATCH] feat: add subscription relation to customer schema and new subscription-related interfaces - Introduced a one-to-one relation for 'subscription' in the customer schema to link customers with their subscriptions. - Added new TypeScript interfaces for subscription-related entities, including Subscription, SubscriptionHistory, SubscriptionPrice, and SubscriptionSetting, ensuring type safety and consistency across the application. --- .../content-types/customer/schema.json | 6 + .../subscription-history/schema.json | 76 +++++++ .../controllers/subscription-history.ts | 7 + .../routes/subscription-history.ts | 7 + .../services/subscription-history.ts | 7 + .../subscription-price/schema.json | 43 ++++ .../controllers/subscription-price.ts | 7 + .../routes/subscription-price.ts | 7 + .../services/subscription-price.ts | 7 + .../subscription-setting/schema.json | 42 ++++ .../controllers/subscription-setting.ts | 7 + .../routes/subscription-setting.ts | 7 + .../services/subscription-setting.ts | 7 + .../content-types/subscription/schema.json | 61 ++++++ .../subscription/controllers/subscription.ts | 7 + src/api/subscription/routes/subscription.ts | 7 + src/api/subscription/services/subscription.ts | 7 + types/generated/contentTypes.d.ts | 189 ++++++++++++++++++ 18 files changed, 501 insertions(+) create mode 100644 src/api/subscription-history/content-types/subscription-history/schema.json create mode 100644 src/api/subscription-history/controllers/subscription-history.ts create mode 100644 src/api/subscription-history/routes/subscription-history.ts create mode 100644 src/api/subscription-history/services/subscription-history.ts create mode 100644 src/api/subscription-price/content-types/subscription-price/schema.json create mode 100644 src/api/subscription-price/controllers/subscription-price.ts create mode 100644 src/api/subscription-price/routes/subscription-price.ts create mode 100644 src/api/subscription-price/services/subscription-price.ts create mode 100644 src/api/subscription-setting/content-types/subscription-setting/schema.json create mode 100644 src/api/subscription-setting/controllers/subscription-setting.ts create mode 100644 src/api/subscription-setting/routes/subscription-setting.ts create mode 100644 src/api/subscription-setting/services/subscription-setting.ts create mode 100644 src/api/subscription/content-types/subscription/schema.json create mode 100644 src/api/subscription/controllers/subscription.ts create mode 100644 src/api/subscription/routes/subscription.ts create mode 100644 src/api/subscription/services/subscription.ts diff --git a/src/api/customer/content-types/customer/schema.json b/src/api/customer/content-types/customer/schema.json index 4a3cf11..6f11f2a 100644 --- a/src/api/customer/content-types/customer/schema.json +++ b/src/api/customer/content-types/customer/schema.json @@ -79,6 +79,12 @@ "target": "api::service.service", "mappedBy": "master" }, + "subscription": { + "type": "relation", + "relation": "oneToOne", + "target": "api::subscription.subscription", + "mappedBy": "customer" + }, "bannedUntil": { "type": "datetime" } diff --git a/src/api/subscription-history/content-types/subscription-history/schema.json b/src/api/subscription-history/content-types/subscription-history/schema.json new file mode 100644 index 0000000..b11aa6b --- /dev/null +++ b/src/api/subscription-history/content-types/subscription-history/schema.json @@ -0,0 +1,76 @@ +{ + "kind": "collectionType", + "collectionName": "subscription_histories", + "info": { + "singularName": "subscription-history", + "pluralName": "subscription-histories", + "displayName": "SubscriptionHistory" + }, + "options": { + "draftAndPublish": true + }, + "pluginOptions": {}, + "attributes": { + "subscription": { + "type": "relation", + "relation": "manyToOne", + "target": "api::subscription.subscription", + "inversedBy": "subscriptionHistories" + }, + "period": { + "type": "enumeration", + "required": true, + "enum": [ + "trial", + "week", + "month", + "half_year", + "year" + ] + }, + "startDate": { + "type": "datetime", + "required": true + }, + "endDate": { + "type": "datetime", + "required": true + }, + "amount": { + "type": "decimal", + "required": true + }, + "currency": { + "type": "string", + "default": "RUB", + "required": false + }, + "state": { + "type": "enumeration", + "required": true, + "enum": [ + "success", + "failed", + "pending" + ] + }, + "paymentId": { + "type": "string", + "required": false + }, + "source": { + "type": "enumeration", + "required": true, + "default": "payment", + "enum": [ + "payment", + "referral", + "admin", + "promo" + ] + }, + "description": { + "type": "text" + } + } +} diff --git a/src/api/subscription-history/controllers/subscription-history.ts b/src/api/subscription-history/controllers/subscription-history.ts new file mode 100644 index 0000000..6e1dffe --- /dev/null +++ b/src/api/subscription-history/controllers/subscription-history.ts @@ -0,0 +1,7 @@ +/** + * subscription-history controller + */ + +import { factories } from '@strapi/strapi' + +export default factories.createCoreController('api::subscription-history.subscription-history'); diff --git a/src/api/subscription-history/routes/subscription-history.ts b/src/api/subscription-history/routes/subscription-history.ts new file mode 100644 index 0000000..b77f819 --- /dev/null +++ b/src/api/subscription-history/routes/subscription-history.ts @@ -0,0 +1,7 @@ +/** + * subscription-history router + */ + +import { factories } from '@strapi/strapi'; + +export default factories.createCoreRouter('api::subscription-history.subscription-history'); diff --git a/src/api/subscription-history/services/subscription-history.ts b/src/api/subscription-history/services/subscription-history.ts new file mode 100644 index 0000000..3ae15fa --- /dev/null +++ b/src/api/subscription-history/services/subscription-history.ts @@ -0,0 +1,7 @@ +/** + * subscription-history service + */ + +import { factories } from '@strapi/strapi'; + +export default factories.createCoreService('api::subscription-history.subscription-history'); diff --git a/src/api/subscription-price/content-types/subscription-price/schema.json b/src/api/subscription-price/content-types/subscription-price/schema.json new file mode 100644 index 0000000..8eca092 --- /dev/null +++ b/src/api/subscription-price/content-types/subscription-price/schema.json @@ -0,0 +1,43 @@ +{ + "kind": "collectionType", + "collectionName": "subscription_prices", + "info": { + "singularName": "subscription-price", + "pluralName": "subscription-prices", + "displayName": "SubscriptionPrice" + }, + "options": { + "draftAndPublish": true + }, + "pluginOptions": {}, + "attributes": { + "period": { + "type": "enumeration", + "required": true, + "enum": [ + "trial", + "week", + "month", + "half_year", + "year" + ] + }, + "price": { + "type": "decimal", + "required": true + }, + "currency": { + "type": "string", + "default": "RUB", + "required": false + }, + "isActive": { + "type": "boolean", + "required": false, + "default": true + }, + "description": { + "type": "text" + } + } +} diff --git a/src/api/subscription-price/controllers/subscription-price.ts b/src/api/subscription-price/controllers/subscription-price.ts new file mode 100644 index 0000000..c24b8ee --- /dev/null +++ b/src/api/subscription-price/controllers/subscription-price.ts @@ -0,0 +1,7 @@ +/** + * subscription-price controller + */ + +import { factories } from '@strapi/strapi' + +export default factories.createCoreController('api::subscription-price.subscription-price'); diff --git a/src/api/subscription-price/routes/subscription-price.ts b/src/api/subscription-price/routes/subscription-price.ts new file mode 100644 index 0000000..b9543e7 --- /dev/null +++ b/src/api/subscription-price/routes/subscription-price.ts @@ -0,0 +1,7 @@ +/** + * subscription-price router + */ + +import { factories } from '@strapi/strapi'; + +export default factories.createCoreRouter('api::subscription-price.subscription-price'); diff --git a/src/api/subscription-price/services/subscription-price.ts b/src/api/subscription-price/services/subscription-price.ts new file mode 100644 index 0000000..86c189f --- /dev/null +++ b/src/api/subscription-price/services/subscription-price.ts @@ -0,0 +1,7 @@ +/** + * subscription-price service + */ + +import { factories } from '@strapi/strapi'; + +export default factories.createCoreService('api::subscription-price.subscription-price'); diff --git a/src/api/subscription-setting/content-types/subscription-setting/schema.json b/src/api/subscription-setting/content-types/subscription-setting/schema.json new file mode 100644 index 0000000..5d76749 --- /dev/null +++ b/src/api/subscription-setting/content-types/subscription-setting/schema.json @@ -0,0 +1,42 @@ +{ + "kind": "singleType", + "collectionName": "subscription_settings", + "info": { + "singularName": "subscription-setting", + "pluralName": "subscription-settings", + "displayName": "SubscriptionSettings" + }, + "options": { + "draftAndPublish": true + }, + "pluginOptions": {}, + "attributes": { + "maxOrdersPerMonth": { + "type": "integer", + "required": true, + "default": 30 + }, + "referralRewardDays": { + "type": "integer", + "required": true, + "default": 3 + }, + "referralBonusDays": { + "type": "integer", + "required": true, + "default": 1 + }, + "description": { + "type": "text" + }, + "trialPeriodDays": { + "type": "integer", + "required": true, + "default": 7 + }, + "trialEnabled": { + "type": "boolean", + "required": true + } + } +} diff --git a/src/api/subscription-setting/controllers/subscription-setting.ts b/src/api/subscription-setting/controllers/subscription-setting.ts new file mode 100644 index 0000000..c022685 --- /dev/null +++ b/src/api/subscription-setting/controllers/subscription-setting.ts @@ -0,0 +1,7 @@ +/** + * subscription-setting controller + */ + +import { factories } from '@strapi/strapi' + +export default factories.createCoreController('api::subscription-setting.subscription-setting'); diff --git a/src/api/subscription-setting/routes/subscription-setting.ts b/src/api/subscription-setting/routes/subscription-setting.ts new file mode 100644 index 0000000..38b6b60 --- /dev/null +++ b/src/api/subscription-setting/routes/subscription-setting.ts @@ -0,0 +1,7 @@ +/** + * subscription-setting router + */ + +import { factories } from '@strapi/strapi'; + +export default factories.createCoreRouter('api::subscription-setting.subscription-setting'); diff --git a/src/api/subscription-setting/services/subscription-setting.ts b/src/api/subscription-setting/services/subscription-setting.ts new file mode 100644 index 0000000..e430ece --- /dev/null +++ b/src/api/subscription-setting/services/subscription-setting.ts @@ -0,0 +1,7 @@ +/** + * subscription-setting service + */ + +import { factories } from '@strapi/strapi'; + +export default factories.createCoreService('api::subscription-setting.subscription-setting'); diff --git a/src/api/subscription/content-types/subscription/schema.json b/src/api/subscription/content-types/subscription/schema.json new file mode 100644 index 0000000..a25e49e --- /dev/null +++ b/src/api/subscription/content-types/subscription/schema.json @@ -0,0 +1,61 @@ +{ + "kind": "collectionType", + "collectionName": "subscriptions", + "info": { + "singularName": "subscription", + "pluralName": "subscriptions", + "displayName": "Subscription" + }, + "options": { + "draftAndPublish": true + }, + "pluginOptions": {}, + "attributes": { + "customer": { + "type": "relation", + "relation": "oneToOne", + "target": "api::customer.customer", + "inversedBy": "subscription" + }, + "isActive": { + "type": "boolean", + "required": true, + "default": false + }, + "expiresAt": { + "type": "datetime", + "required": false + }, + "autoRenew": { + "type": "boolean", + "required": true, + "default": false + }, + "referralCode": { + "type": "string", + "required": true, + "unique": true + }, + "subscription": { + "type": "relation", + "relation": "oneToOne", + "target": "api::subscription.subscription" + }, + "referralCount": { + "type": "integer", + "required": true, + "default": 0 + }, + "subscriptionHistories": { + "type": "relation", + "relation": "oneToMany", + "target": "api::subscription-history.subscription-history", + "mappedBy": "subscription" + }, + "referredBy": { + "type": "relation", + "relation": "oneToOne", + "target": "api::subscription.subscription" + } + } +} diff --git a/src/api/subscription/controllers/subscription.ts b/src/api/subscription/controllers/subscription.ts new file mode 100644 index 0000000..a902ed5 --- /dev/null +++ b/src/api/subscription/controllers/subscription.ts @@ -0,0 +1,7 @@ +/** + * subscription controller + */ + +import { factories } from '@strapi/strapi' + +export default factories.createCoreController('api::subscription.subscription'); diff --git a/src/api/subscription/routes/subscription.ts b/src/api/subscription/routes/subscription.ts new file mode 100644 index 0000000..7851cae --- /dev/null +++ b/src/api/subscription/routes/subscription.ts @@ -0,0 +1,7 @@ +/** + * subscription router + */ + +import { factories } from '@strapi/strapi'; + +export default factories.createCoreRouter('api::subscription.subscription'); diff --git a/src/api/subscription/services/subscription.ts b/src/api/subscription/services/subscription.ts new file mode 100644 index 0000000..557b264 --- /dev/null +++ b/src/api/subscription/services/subscription.ts @@ -0,0 +1,7 @@ +/** + * subscription service + */ + +import { factories } from '@strapi/strapi'; + +export default factories.createCoreService('api::subscription.subscription'); diff --git a/types/generated/contentTypes.d.ts b/types/generated/contentTypes.d.ts index 45dea69..542ec22 100644 --- a/types/generated/contentTypes.d.ts +++ b/types/generated/contentTypes.d.ts @@ -454,6 +454,10 @@ export interface ApiCustomerCustomer extends Struct.CollectionTypeSchema { Schema.Attribute.Required; services: Schema.Attribute.Relation<'oneToMany', 'api::service.service'>; slots: Schema.Attribute.Relation<'oneToMany', 'api::slot.slot'>; + subscription: Schema.Attribute.Relation< + 'oneToOne', + 'api::subscription.subscription' + >; telegramId: Schema.Attribute.BigInteger & Schema.Attribute.Unique; updatedAt: Schema.Attribute.DateTime; updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & @@ -611,6 +615,187 @@ export interface ApiSlotSlot extends Struct.CollectionTypeSchema { }; } +export interface ApiSubscriptionHistorySubscriptionHistory + extends Struct.CollectionTypeSchema { + collectionName: 'subscription_histories'; + info: { + displayName: 'SubscriptionHistory'; + pluralName: 'subscription-histories'; + singularName: 'subscription-history'; + }; + options: { + draftAndPublish: true; + }; + attributes: { + amount: Schema.Attribute.Decimal & Schema.Attribute.Required; + createdAt: Schema.Attribute.DateTime; + createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & + Schema.Attribute.Private; + currency: Schema.Attribute.String & Schema.Attribute.DefaultTo<'RUB'>; + description: Schema.Attribute.Text; + endDate: Schema.Attribute.DateTime & Schema.Attribute.Required; + locale: Schema.Attribute.String & Schema.Attribute.Private; + localizations: Schema.Attribute.Relation< + 'oneToMany', + 'api::subscription-history.subscription-history' + > & + Schema.Attribute.Private; + paymentId: Schema.Attribute.String; + period: Schema.Attribute.Enumeration< + ['trial', 'week', 'month', 'half_year', 'year'] + > & + Schema.Attribute.Required; + publishedAt: Schema.Attribute.DateTime; + source: Schema.Attribute.Enumeration< + ['payment', 'referral', 'admin', 'promo'] + > & + Schema.Attribute.Required & + Schema.Attribute.DefaultTo<'payment'>; + startDate: Schema.Attribute.DateTime & Schema.Attribute.Required; + state: Schema.Attribute.Enumeration<['success', 'failed', 'pending']> & + Schema.Attribute.Required; + subscription: Schema.Attribute.Relation< + 'manyToOne', + 'api::subscription.subscription' + >; + updatedAt: Schema.Attribute.DateTime; + updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & + Schema.Attribute.Private; + }; +} + +export interface ApiSubscriptionPriceSubscriptionPrice + extends Struct.CollectionTypeSchema { + collectionName: 'subscription_prices'; + info: { + displayName: 'SubscriptionPrice'; + pluralName: 'subscription-prices'; + singularName: 'subscription-price'; + }; + options: { + draftAndPublish: true; + }; + attributes: { + createdAt: Schema.Attribute.DateTime; + createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & + Schema.Attribute.Private; + currency: Schema.Attribute.String & Schema.Attribute.DefaultTo<'RUB'>; + description: Schema.Attribute.Text; + isActive: Schema.Attribute.Boolean & Schema.Attribute.DefaultTo; + locale: Schema.Attribute.String & Schema.Attribute.Private; + localizations: Schema.Attribute.Relation< + 'oneToMany', + 'api::subscription-price.subscription-price' + > & + Schema.Attribute.Private; + period: Schema.Attribute.Enumeration< + ['trial', 'week', 'month', 'half_year', 'year'] + > & + Schema.Attribute.Required; + price: Schema.Attribute.Decimal & Schema.Attribute.Required; + publishedAt: Schema.Attribute.DateTime; + updatedAt: Schema.Attribute.DateTime; + updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & + Schema.Attribute.Private; + }; +} + +export interface ApiSubscriptionSettingSubscriptionSetting + extends Struct.SingleTypeSchema { + collectionName: 'subscription_settings'; + info: { + displayName: 'SubscriptionSettings'; + pluralName: 'subscription-settings'; + singularName: 'subscription-setting'; + }; + options: { + draftAndPublish: true; + }; + attributes: { + createdAt: Schema.Attribute.DateTime; + createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & + Schema.Attribute.Private; + description: Schema.Attribute.Text; + locale: Schema.Attribute.String & Schema.Attribute.Private; + localizations: Schema.Attribute.Relation< + 'oneToMany', + 'api::subscription-setting.subscription-setting' + > & + Schema.Attribute.Private; + maxOrdersPerMonth: Schema.Attribute.Integer & + Schema.Attribute.Required & + Schema.Attribute.DefaultTo<30>; + publishedAt: Schema.Attribute.DateTime; + referralBonusDays: Schema.Attribute.Integer & + Schema.Attribute.Required & + Schema.Attribute.DefaultTo<1>; + referralRewardDays: Schema.Attribute.Integer & + Schema.Attribute.Required & + Schema.Attribute.DefaultTo<3>; + trialEnabled: Schema.Attribute.Boolean & Schema.Attribute.Required; + trialPeriodDays: Schema.Attribute.Integer & + Schema.Attribute.Required & + Schema.Attribute.DefaultTo<7>; + updatedAt: Schema.Attribute.DateTime; + updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & + Schema.Attribute.Private; + }; +} + +export interface ApiSubscriptionSubscription + extends Struct.CollectionTypeSchema { + collectionName: 'subscriptions'; + info: { + displayName: 'Subscription'; + pluralName: 'subscriptions'; + singularName: 'subscription'; + }; + options: { + draftAndPublish: true; + }; + attributes: { + autoRenew: Schema.Attribute.Boolean & + Schema.Attribute.Required & + Schema.Attribute.DefaultTo; + createdAt: Schema.Attribute.DateTime; + createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & + Schema.Attribute.Private; + customer: Schema.Attribute.Relation<'oneToOne', 'api::customer.customer'>; + expiresAt: Schema.Attribute.DateTime; + isActive: Schema.Attribute.Boolean & + Schema.Attribute.Required & + Schema.Attribute.DefaultTo; + locale: Schema.Attribute.String & Schema.Attribute.Private; + localizations: Schema.Attribute.Relation< + 'oneToMany', + 'api::subscription.subscription' + > & + Schema.Attribute.Private; + publishedAt: Schema.Attribute.DateTime; + referralCode: Schema.Attribute.String & + Schema.Attribute.Required & + Schema.Attribute.Unique; + referralCount: Schema.Attribute.Integer & + Schema.Attribute.Required & + Schema.Attribute.DefaultTo<0>; + referredBy: Schema.Attribute.Relation< + 'oneToOne', + 'api::subscription.subscription' + >; + subscription: Schema.Attribute.Relation< + 'oneToOne', + 'api::subscription.subscription' + >; + subscriptionHistories: Schema.Attribute.Relation< + 'oneToMany', + 'api::subscription-history.subscription-history' + >; + updatedAt: Schema.Attribute.DateTime; + updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & + Schema.Attribute.Private; + }; +} + export interface PluginContentReleasesRelease extends Struct.CollectionTypeSchema { collectionName: 'strapi_releases'; @@ -1126,6 +1311,10 @@ declare module '@strapi/strapi' { 'api::service.service': ApiServiceService; 'api::setting.setting': ApiSettingSetting; 'api::slot.slot': ApiSlotSlot; + 'api::subscription-history.subscription-history': ApiSubscriptionHistorySubscriptionHistory; + 'api::subscription-price.subscription-price': ApiSubscriptionPriceSubscriptionPrice; + 'api::subscription-setting.subscription-setting': ApiSubscriptionSettingSubscriptionSetting; + 'api::subscription.subscription': ApiSubscriptionSubscription; 'plugin::content-releases.release': PluginContentReleasesRelease; 'plugin::content-releases.release-action': PluginContentReleasesReleaseAction; 'plugin::i18n.locale': PluginI18NLocale;