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.
This commit is contained in:
vchikalkin 2025-08-26 18:53:50 +03:00
parent ccd0947334
commit 2f1fbb8824
18 changed files with 501 additions and 0 deletions

View File

@ -79,6 +79,12 @@
"target": "api::service.service",
"mappedBy": "master"
},
"subscription": {
"type": "relation",
"relation": "oneToOne",
"target": "api::subscription.subscription",
"mappedBy": "customer"
},
"bannedUntil": {
"type": "datetime"
}

View File

@ -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"
}
}
}

View File

@ -0,0 +1,7 @@
/**
* subscription-history controller
*/
import { factories } from '@strapi/strapi'
export default factories.createCoreController('api::subscription-history.subscription-history');

View File

@ -0,0 +1,7 @@
/**
* subscription-history router
*/
import { factories } from '@strapi/strapi';
export default factories.createCoreRouter('api::subscription-history.subscription-history');

View File

@ -0,0 +1,7 @@
/**
* subscription-history service
*/
import { factories } from '@strapi/strapi';
export default factories.createCoreService('api::subscription-history.subscription-history');

View File

@ -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"
}
}
}

View File

@ -0,0 +1,7 @@
/**
* subscription-price controller
*/
import { factories } from '@strapi/strapi'
export default factories.createCoreController('api::subscription-price.subscription-price');

View File

@ -0,0 +1,7 @@
/**
* subscription-price router
*/
import { factories } from '@strapi/strapi';
export default factories.createCoreRouter('api::subscription-price.subscription-price');

View File

@ -0,0 +1,7 @@
/**
* subscription-price service
*/
import { factories } from '@strapi/strapi';
export default factories.createCoreService('api::subscription-price.subscription-price');

View File

@ -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
}
}
}

View File

@ -0,0 +1,7 @@
/**
* subscription-setting controller
*/
import { factories } from '@strapi/strapi'
export default factories.createCoreController('api::subscription-setting.subscription-setting');

View File

@ -0,0 +1,7 @@
/**
* subscription-setting router
*/
import { factories } from '@strapi/strapi';
export default factories.createCoreRouter('api::subscription-setting.subscription-setting');

View File

@ -0,0 +1,7 @@
/**
* subscription-setting service
*/
import { factories } from '@strapi/strapi';
export default factories.createCoreService('api::subscription-setting.subscription-setting');

View File

@ -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"
}
}
}

View File

@ -0,0 +1,7 @@
/**
* subscription controller
*/
import { factories } from '@strapi/strapi'
export default factories.createCoreController('api::subscription.subscription');

View File

@ -0,0 +1,7 @@
/**
* subscription router
*/
import { factories } from '@strapi/strapi';
export default factories.createCoreRouter('api::subscription.subscription');

View File

@ -0,0 +1,7 @@
/**
* subscription service
*/
import { factories } from '@strapi/strapi';
export default factories.createCoreService('api::subscription.subscription');

View File

@ -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<true>;
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<false>;
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<false>;
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;