Implement extension request and gift functionalities in billing system
CI / Backend (build + test) (push) Successful in 1m27s
CI / Frontend (lint + typecheck + build) (push) Successful in 33s

- Added new endpoints for creating and managing extension requests, allowing users to request billing period extensions.
- Implemented admin approval processes for extension requests via Telegram, including inline buttons for approval and rejection.
- Introduced a gifting feature for admins to grant additional billing days directly to users without a request.
- Updated the support ticket model to accommodate extension requests and their associated properties.
- Enhanced the Telegram notifier to inform admins of new extension requests and notify users of approval or rejection.
- Updated frontend components to support the new extension request and gifting functionalities, including user interfaces for managing these features.
- Revised API documentation to reflect the new endpoints and their usage in the billing context.
This commit is contained in:
Leonid Pershin
2026-07-19 05:30:11 +03:00
parent e088e302e9
commit 24cee9bb78
46 changed files with 2541 additions and 78 deletions
+2 -1
View File
@@ -310,7 +310,7 @@ export type AuditLogDto = {
createdAt: string
}
export type TicketType = 'BugReport' | 'RoleRequest'
export type TicketType = 'BugReport' | 'RoleRequest' | 'ExtensionRequest'
export type TicketStatus = 'Open' | 'Resolved' | 'Closed'
export type TicketAttachmentDto = {
@@ -356,6 +356,7 @@ export type TicketDetailDto = {
proposedRoleName: string | null
proposedMaxConfigs: number | null
proposedMaxIpLimit: number | null
requestedDays: number | null
createdAt: string
comments: TicketCommentDto[]
}
+16
View File
@@ -165,6 +165,10 @@ const resources = {
empty: 'У вас пока нет обращений.',
reportBug: 'Сообщить об ошибке',
requestRole: 'Запросить роль',
requestExtension: 'Попросить о продлении',
requestedDaysLabel: 'Сколько дней нужно',
requestedExtension: 'Запрошено продление на {{days}} дн.',
extensionRequestPending: 'У вас уже есть необработанная заявка на продление.',
submit: 'Отправить',
messageLabel: 'Опишите проблему или предложение',
attachmentsLabel: 'Скриншоты (необязательно, до 5)',
@@ -194,6 +198,7 @@ const resources = {
type: {
BugReport: 'Ошибка/предложение',
RoleRequest: 'Заявка на роль',
ExtensionRequest: 'Заявка на продление',
},
status: {
Open: 'Открыт',
@@ -274,6 +279,9 @@ const resources = {
delete: 'Удалить пользователя',
confirmDelete: 'Удалить пользователя? Все его конфиги будут отозваны в 3x-ui, действие необратимо.',
deleted: 'Пользователь удалён.',
giftDaysPlaceholder: 'Дней',
giftGrant: 'Подарить',
giftGranted: 'Дни подписки подарены пользователю.',
},
configs: {
searchPlaceholder: 'Поиск по email в панели или метке',
@@ -681,6 +689,10 @@ const resources = {
empty: 'You have no tickets yet.',
reportBug: 'Report a bug',
requestRole: 'Request a role',
requestExtension: 'Request an extension',
requestedDaysLabel: 'How many days you need',
requestedExtension: 'Requested a {{days}}-day extension',
extensionRequestPending: 'You already have a pending extension request.',
submit: 'Submit',
messageLabel: 'Describe the issue or suggestion',
attachmentsLabel: 'Screenshots (optional, up to 5)',
@@ -710,6 +722,7 @@ const resources = {
type: {
BugReport: 'Bug/suggestion',
RoleRequest: 'Role request',
ExtensionRequest: 'Extension request',
},
status: {
Open: 'Open',
@@ -790,6 +803,9 @@ const resources = {
delete: 'Delete user',
confirmDelete: 'Delete this user? All their configs will be revoked in 3x-ui — this cannot be undone.',
deleted: 'User deleted.',
giftDaysPlaceholder: 'Days',
giftGrant: 'Grant',
giftGranted: 'Subscription days granted to the user.',
},
configs: {
searchPlaceholder: 'Search by panel email or label',