Compare commits
24 Commits
refactor/m
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6b788a9024 | ||
|
|
0e58a8cef7 | ||
|
|
a63eff9f46 | ||
|
|
e0a9f55eeb | ||
|
|
ccd0947334 | ||
|
|
37c28353a9 | ||
|
|
01fbd1c696 | ||
|
|
8a81a1e251 | ||
|
|
3fb75f5765 | ||
|
|
d9ac6858e7 | ||
|
|
9f1b13192f | ||
|
|
b0aa644435 | ||
|
|
63a68c6089 | ||
|
|
7a89cfa7ce | ||
|
|
cfa5a02ca9 | ||
|
|
50f23f67b3 | ||
|
|
3833a1a23d | ||
|
|
d592c9cf31 | ||
|
|
34fff838f9 | ||
|
|
8b2c7396c3 | ||
|
|
c22357b71e | ||
|
|
7f57b03c88 | ||
|
|
6dc36ebe89 | ||
|
|
b0171aa079 |
13
.github/workflows/deploy.yml
vendored
13
.github/workflows/deploy.yml
vendored
@ -9,19 +9,25 @@ jobs:
|
|||||||
build-and-push:
|
build-and-push:
|
||||||
name: Build and Push to Docker Hub
|
name: Build and Push to Docker Hub
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
outputs:
|
||||||
|
tag: ${{ steps.vars.outputs.tag }}
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Set image tag
|
||||||
|
id: vars
|
||||||
|
run: echo "tag=${GITHUB_SHA::7}" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
- name: Login to Docker Hub
|
- name: Login to Docker Hub
|
||||||
run: echo "${{ secrets.DOCKERHUB_TOKEN }}" | docker login -u "${{ secrets.DOCKERHUB_USERNAME }}" --password-stdin
|
run: echo "${{ secrets.DOCKERHUB_TOKEN }}" | docker login -u "${{ secrets.DOCKERHUB_USERNAME }}" --password-stdin
|
||||||
|
|
||||||
- name: Build image
|
- name: Build image
|
||||||
run: docker build -t ${{ secrets.DOCKERHUB_USERNAME }}/zapishis-strapi:latest .
|
run: docker build -t ${{ secrets.DOCKERHUB_USERNAME }}/zapishis-strapi:${{ steps.vars.outputs.tag }} .
|
||||||
|
|
||||||
- name: Push image to Docker Hub
|
- name: Push image to Docker Hub
|
||||||
run: docker push ${{ secrets.DOCKERHUB_USERNAME }}/zapishis-strapi:latest
|
run: docker push ${{ secrets.DOCKERHUB_USERNAME }}/zapishis-strapi:${{ steps.vars.outputs.tag }}
|
||||||
|
|
||||||
deploy:
|
deploy:
|
||||||
name: Deploy to VPS
|
name: Deploy to VPS
|
||||||
@ -57,6 +63,9 @@ jobs:
|
|||||||
echo "DATABASE_USERNAME=${{ secrets.DATABASE_USERNAME }}" >> .env
|
echo "DATABASE_USERNAME=${{ secrets.DATABASE_USERNAME }}" >> .env
|
||||||
echo "DATABASE_PASSWORD=${{ secrets.DATABASE_PASSWORD }}" >> .env
|
echo "DATABASE_PASSWORD=${{ secrets.DATABASE_PASSWORD }}" >> .env
|
||||||
echo "DATABASE_SSL=false" >> .env
|
echo "DATABASE_SSL=false" >> .env
|
||||||
|
echo "BOT_TOKEN=${{ secrets.BOT_TOKEN }}" >> .env
|
||||||
|
echo "DOCKERHUB_USERNAME=${{ secrets.DOCKERHUB_USERNAME }}" >> .env
|
||||||
|
echo "STRAPI_IMAGE_TAG=${{ needs.build-and-push.outputs.tag }}" >> .env
|
||||||
|
|
||||||
- name: Copy .env to VPS via SCP
|
- name: Copy .env to VPS via SCP
|
||||||
uses: appleboy/scp-action@master
|
uses: appleboy/scp-action@master
|
||||||
|
|||||||
4
.gitignore
vendored
4
.gitignore
vendored
@ -128,4 +128,6 @@ exports
|
|||||||
dist
|
dist
|
||||||
build
|
build
|
||||||
.strapi-updater.json
|
.strapi-updater.json
|
||||||
.strapi-cloud.json
|
.strapi-cloud.json
|
||||||
|
|
||||||
|
*.cmd
|
||||||
@ -1,6 +1,7 @@
|
|||||||
export default ({ env }) => ({
|
export default ({ env }) => ({
|
||||||
host: env('HOST', '0.0.0.0'),
|
host: env('HOST', '0.0.0.0'),
|
||||||
port: env.int('PORT', 1337),
|
port: env.int('PORT', 1337),
|
||||||
|
botToken: env('BOT_TOKEN', undefined),
|
||||||
app: {
|
app: {
|
||||||
keys: env.array('APP_KEYS'),
|
keys: env.array('APP_KEYS'),
|
||||||
},
|
},
|
||||||
|
|||||||
28
docker-compose.dev.yml
Normal file
28
docker-compose.dev.yml
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
services:
|
||||||
|
postgres:
|
||||||
|
image: postgres
|
||||||
|
ports:
|
||||||
|
- '127.0.0.1:5432:5432'
|
||||||
|
environment:
|
||||||
|
POSTGRES_USER: ${DATABASE_USERNAME}
|
||||||
|
POSTGRES_PASSWORD: ${DATABASE_PASSWORD}
|
||||||
|
POSTGRES_DB: ${DATABASE_NAME}
|
||||||
|
strapi:
|
||||||
|
build: .
|
||||||
|
ports:
|
||||||
|
- '127.0.0.1:1337:1337'
|
||||||
|
environment:
|
||||||
|
APP_KEYS: ${APP_KEYS}
|
||||||
|
API_TOKEN_SALT: ${API_TOKEN_SALT}
|
||||||
|
ADMIN_JWT_SECRET: ${ADMIN_JWT_SECRET}
|
||||||
|
TRANSFER_TOKEN_SALT: ${TRANSFER_TOKEN_SALT}
|
||||||
|
JWT_SECRET: ${JWT_SECRET}
|
||||||
|
DATABASE_HOST: ${DATABASE_HOST}
|
||||||
|
DATABASE_PORT: ${DATABASE_PORT}
|
||||||
|
DATABASE_NAME: ${DATABASE_NAME}
|
||||||
|
DATABASE_USERNAME: ${DATABASE_USERNAME}
|
||||||
|
DATABASE_PASSWORD: ${DATABASE_PASSWORD}
|
||||||
|
DATABASE_SSL: 'false'
|
||||||
|
BOT_TOKEN: ${BOT_TOKEN}
|
||||||
|
|
||||||
|
|
||||||
@ -1,6 +1,6 @@
|
|||||||
services:
|
services:
|
||||||
strapi:
|
strapi:
|
||||||
image: vchikalkin/zapishis-strapi:latest
|
image: ${DOCKERHUB_USERNAME}/zapishis-strapi:${STRAPI_IMAGE_TAG}
|
||||||
ports:
|
ports:
|
||||||
- "127.0.0.1:1337:1337"
|
- "127.0.0.1:1337:1337"
|
||||||
environment:
|
environment:
|
||||||
@ -15,6 +15,7 @@ services:
|
|||||||
DATABASE_USERNAME: ${DATABASE_USERNAME}
|
DATABASE_USERNAME: ${DATABASE_USERNAME}
|
||||||
DATABASE_PASSWORD: ${DATABASE_PASSWORD}
|
DATABASE_PASSWORD: ${DATABASE_PASSWORD}
|
||||||
DATABASE_SSL: "false"
|
DATABASE_SSL: "false"
|
||||||
|
BOT_TOKEN: ${BOT_TOKEN}
|
||||||
networks:
|
networks:
|
||||||
- app
|
- app
|
||||||
|
|
||||||
|
|||||||
@ -15,11 +15,13 @@
|
|||||||
"@strapi/plugin-graphql": "^5.15.0",
|
"@strapi/plugin-graphql": "^5.15.0",
|
||||||
"@strapi/plugin-users-permissions": "5.15.0",
|
"@strapi/plugin-users-permissions": "5.15.0",
|
||||||
"@strapi/strapi": "5.15.0",
|
"@strapi/strapi": "5.15.0",
|
||||||
|
"dayjs": "^1.11.13",
|
||||||
"pg": "8.8.0",
|
"pg": "8.8.0",
|
||||||
"react": "^18.0.0",
|
"react": "^18.0.0",
|
||||||
"react-dom": "^18.0.0",
|
"react-dom": "^18.0.0",
|
||||||
"react-router-dom": "^6.0.0",
|
"react-router-dom": "^6.0.0",
|
||||||
"styled-components": "^6.0.0"
|
"styled-components": "^6.0.0",
|
||||||
|
"telegraf": "^4.16.3"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/node": "^20",
|
"@types/node": "^20",
|
||||||
|
|||||||
136
pnpm-lock.yaml
generated
136
pnpm-lock.yaml
generated
@ -20,6 +20,9 @@ importers:
|
|||||||
'@strapi/strapi':
|
'@strapi/strapi':
|
||||||
specifier: 5.15.0
|
specifier: 5.15.0
|
||||||
version: 5.15.0(@babel/runtime@7.26.0)(@codemirror/autocomplete@6.18.3(@codemirror/language@6.10.5)(@codemirror/state@6.4.1)(@codemirror/view@6.35.0)(@lezer/common@1.2.3))(@codemirror/language@6.10.5)(@codemirror/lint@6.8.4)(@codemirror/search@6.5.8)(@codemirror/state@6.4.1)(@codemirror/theme-one-dark@6.1.2)(@codemirror/view@6.35.0)(@swc/helpers@0.5.15)(@types/hoist-non-react-statics@3.3.5)(@types/node@20.17.9)(@types/react-dom@18.3.1)(@types/react@18.3.12)(codemirror@5.65.18)(esbuild@0.25.5)(koa@2.16.1)(pg@8.8.0)(react-dom@18.3.1(react@18.3.1))(react-router-dom@6.28.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1)(redux@4.2.1)(styled-components@6.1.13(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(terser@5.36.0)(type-fest@4.29.0)
|
version: 5.15.0(@babel/runtime@7.26.0)(@codemirror/autocomplete@6.18.3(@codemirror/language@6.10.5)(@codemirror/state@6.4.1)(@codemirror/view@6.35.0)(@lezer/common@1.2.3))(@codemirror/language@6.10.5)(@codemirror/lint@6.8.4)(@codemirror/search@6.5.8)(@codemirror/state@6.4.1)(@codemirror/theme-one-dark@6.1.2)(@codemirror/view@6.35.0)(@swc/helpers@0.5.15)(@types/hoist-non-react-statics@3.3.5)(@types/node@20.17.9)(@types/react-dom@18.3.1)(@types/react@18.3.12)(codemirror@5.65.18)(esbuild@0.25.5)(koa@2.16.1)(pg@8.8.0)(react-dom@18.3.1(react@18.3.1))(react-router-dom@6.28.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1)(redux@4.2.1)(styled-components@6.1.13(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(terser@5.36.0)(type-fest@4.29.0)
|
||||||
|
dayjs:
|
||||||
|
specifier: ^1.11.13
|
||||||
|
version: 1.11.13
|
||||||
pg:
|
pg:
|
||||||
specifier: 8.8.0
|
specifier: 8.8.0
|
||||||
version: 8.8.0
|
version: 8.8.0
|
||||||
@ -35,6 +38,9 @@ importers:
|
|||||||
styled-components:
|
styled-components:
|
||||||
specifier: ^6.0.0
|
specifier: ^6.0.0
|
||||||
version: 6.1.13(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
version: 6.1.13(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||||
|
telegraf:
|
||||||
|
specifier: ^4.16.3
|
||||||
|
version: 4.16.3
|
||||||
devDependencies:
|
devDependencies:
|
||||||
'@types/node':
|
'@types/node':
|
||||||
specifier: ^20
|
specifier: ^20
|
||||||
@ -1897,6 +1903,9 @@ packages:
|
|||||||
resolution: {integrity: sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==}
|
resolution: {integrity: sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==}
|
||||||
engines: {node: '>=10'}
|
engines: {node: '>=10'}
|
||||||
|
|
||||||
|
'@telegraf/types@7.1.0':
|
||||||
|
resolution: {integrity: sha512-kGevOIbpMcIlCDeorKGpwZmdH7kHbqlk/Yj6dEpJMKEQw5lk0KVQY0OLXaCswy8GqlIVLd5625OB+rAntP9xVw==}
|
||||||
|
|
||||||
'@testing-library/dom@10.1.0':
|
'@testing-library/dom@10.1.0':
|
||||||
resolution: {integrity: sha512-wdsYKy5zupPyLCW2Je5DLHSxSfbIp6h80WoHOQc+RPtmPGA52O9x5MJEkv92Sjonpq+poOAtUKhh1kBGAXBrNA==}
|
resolution: {integrity: sha512-wdsYKy5zupPyLCW2Je5DLHSxSfbIp6h80WoHOQc+RPtmPGA52O9x5MJEkv92Sjonpq+poOAtUKhh1kBGAXBrNA==}
|
||||||
engines: {node: '>=18'}
|
engines: {node: '>=18'}
|
||||||
@ -2182,6 +2191,10 @@ packages:
|
|||||||
'@xtuc/long@4.2.2':
|
'@xtuc/long@4.2.2':
|
||||||
resolution: {integrity: sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==}
|
resolution: {integrity: sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==}
|
||||||
|
|
||||||
|
abort-controller@3.0.0:
|
||||||
|
resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==}
|
||||||
|
engines: {node: '>=6.5'}
|
||||||
|
|
||||||
accepts@1.3.8:
|
accepts@1.3.8:
|
||||||
resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==}
|
resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==}
|
||||||
engines: {node: '>= 0.6'}
|
engines: {node: '>= 0.6'}
|
||||||
@ -2419,9 +2432,18 @@ packages:
|
|||||||
engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
|
engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
||||||
|
buffer-alloc-unsafe@1.1.0:
|
||||||
|
resolution: {integrity: sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==}
|
||||||
|
|
||||||
|
buffer-alloc@1.2.0:
|
||||||
|
resolution: {integrity: sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==}
|
||||||
|
|
||||||
buffer-equal-constant-time@1.0.1:
|
buffer-equal-constant-time@1.0.1:
|
||||||
resolution: {integrity: sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==}
|
resolution: {integrity: sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==}
|
||||||
|
|
||||||
|
buffer-fill@1.0.0:
|
||||||
|
resolution: {integrity: sha512-T7zexNBwiiaCOGDg9xNX9PBmjrubblRkENuptryuI64URkXDFum9il/JGL8Lm8wYfAXpredVXXZz7eMHilimiQ==}
|
||||||
|
|
||||||
buffer-from@1.1.2:
|
buffer-from@1.1.2:
|
||||||
resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==}
|
resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==}
|
||||||
|
|
||||||
@ -2808,6 +2830,9 @@ packages:
|
|||||||
resolution: {integrity: sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==}
|
resolution: {integrity: sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==}
|
||||||
engines: {node: '>=0.11'}
|
engines: {node: '>=0.11'}
|
||||||
|
|
||||||
|
dayjs@1.11.13:
|
||||||
|
resolution: {integrity: sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==}
|
||||||
|
|
||||||
debounce@1.2.1:
|
debounce@1.2.1:
|
||||||
resolution: {integrity: sha512-XRRe6Glud4rd/ZGQfiV1ruXSfbvfJedlV9Y6zOlP+2K04vBYiJEte6stfFkCP03aMnY5tsipamumUjL14fofug==}
|
resolution: {integrity: sha512-XRRe6Glud4rd/ZGQfiV1ruXSfbvfJedlV9Y6zOlP+2K04vBYiJEte6stfFkCP03aMnY5tsipamumUjL14fofug==}
|
||||||
|
|
||||||
@ -3159,6 +3184,10 @@ packages:
|
|||||||
resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==}
|
resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==}
|
||||||
engines: {node: '>= 0.6'}
|
engines: {node: '>= 0.6'}
|
||||||
|
|
||||||
|
event-target-shim@5.0.1:
|
||||||
|
resolution: {integrity: sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==}
|
||||||
|
engines: {node: '>=6'}
|
||||||
|
|
||||||
events@3.3.0:
|
events@3.3.0:
|
||||||
resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==}
|
resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==}
|
||||||
engines: {node: '>=0.8.x'}
|
engines: {node: '>=0.8.x'}
|
||||||
@ -4409,6 +4438,10 @@ packages:
|
|||||||
engines: {node: '>=10'}
|
engines: {node: '>=10'}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
||||||
|
mri@1.2.0:
|
||||||
|
resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==}
|
||||||
|
engines: {node: '>=4'}
|
||||||
|
|
||||||
mrmime@2.0.0:
|
mrmime@2.0.0:
|
||||||
resolution: {integrity: sha512-eu38+hdgojoyq63s+yTpN4XMBdt5l8HhMhc4VKLO9KM5caLIBvUm4thi7fFaxyTmCKeNnXZ5pAlBwCUnhA09uw==}
|
resolution: {integrity: sha512-eu38+hdgojoyq63s+yTpN4XMBdt5l8HhMhc4VKLO9KM5caLIBvUm4thi7fFaxyTmCKeNnXZ5pAlBwCUnhA09uw==}
|
||||||
engines: {node: '>=10'}
|
engines: {node: '>=10'}
|
||||||
@ -4654,6 +4687,10 @@ packages:
|
|||||||
resolution: {integrity: sha512-VFqfGDHlx87K66yZrNdI4YGtD70IRyd+zSvgks6mzHPRNkoKy+9EKP4SFC77/vTTQYmRmti7dvqC+m5jBrBAcg==}
|
resolution: {integrity: sha512-VFqfGDHlx87K66yZrNdI4YGtD70IRyd+zSvgks6mzHPRNkoKy+9EKP4SFC77/vTTQYmRmti7dvqC+m5jBrBAcg==}
|
||||||
engines: {node: '>=12'}
|
engines: {node: '>=12'}
|
||||||
|
|
||||||
|
p-timeout@4.1.0:
|
||||||
|
resolution: {integrity: sha512-+/wmHtzJuWii1sXn3HCuH/FTwGhrp4tmJTxSKJbfS+vkipci6osxXM5mY0jUiRzWKMTgUT8l7HFbeSwZAynqHw==}
|
||||||
|
engines: {node: '>=10'}
|
||||||
|
|
||||||
p-try@2.2.0:
|
p-try@2.2.0:
|
||||||
resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==}
|
resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==}
|
||||||
engines: {node: '>=6'}
|
engines: {node: '>=6'}
|
||||||
@ -5339,6 +5376,9 @@ packages:
|
|||||||
safe-buffer@5.2.1:
|
safe-buffer@5.2.1:
|
||||||
resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==}
|
resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==}
|
||||||
|
|
||||||
|
safe-compare@1.1.4:
|
||||||
|
resolution: {integrity: sha512-b9wZ986HHCo/HbKrRpBJb2kqXMK9CEWIE1egeEvZsYn69ay3kdfl9nG3RyOcR+jInTDf7a86WQ1d4VJX7goSSQ==}
|
||||||
|
|
||||||
safe-stable-stringify@2.5.0:
|
safe-stable-stringify@2.5.0:
|
||||||
resolution: {integrity: sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==}
|
resolution: {integrity: sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==}
|
||||||
engines: {node: '>=10'}
|
engines: {node: '>=10'}
|
||||||
@ -5346,6 +5386,10 @@ packages:
|
|||||||
safer-buffer@2.1.2:
|
safer-buffer@2.1.2:
|
||||||
resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==}
|
resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==}
|
||||||
|
|
||||||
|
sandwich-stream@2.0.2:
|
||||||
|
resolution: {integrity: sha512-jLYV0DORrzY3xaz/S9ydJL6Iz7essZeAfnAavsJ+zsJGZ1MOnsS52yRjU3uF3pJa/lla7+wisp//fxOwOH8SKQ==}
|
||||||
|
engines: {node: '>= 0.10'}
|
||||||
|
|
||||||
sanitize-html@2.13.0:
|
sanitize-html@2.13.0:
|
||||||
resolution: {integrity: sha512-Xff91Z+4Mz5QiNSLdLWwjgBDm5b1RU6xBT0+12rapjiaR7SwfRdjw8f+6Rir2MXKLrDicRFHdb51hGOAxmsUIA==}
|
resolution: {integrity: sha512-Xff91Z+4Mz5QiNSLdLWwjgBDm5b1RU6xBT0+12rapjiaR7SwfRdjw8f+6Rir2MXKLrDicRFHdb51hGOAxmsUIA==}
|
||||||
|
|
||||||
@ -5684,6 +5728,11 @@ packages:
|
|||||||
resolution: {integrity: sha512-51LAVKUSZSVfI05vjPESNc5vwqqZpbXCsU+/+wxlOrUjk2SnFTt97v9ZgQrD4YmxYW1Px6w2KjaDitCfkvgxMQ==}
|
resolution: {integrity: sha512-51LAVKUSZSVfI05vjPESNc5vwqqZpbXCsU+/+wxlOrUjk2SnFTt97v9ZgQrD4YmxYW1Px6w2KjaDitCfkvgxMQ==}
|
||||||
engines: {node: '>=8.0.0'}
|
engines: {node: '>=8.0.0'}
|
||||||
|
|
||||||
|
telegraf@4.16.3:
|
||||||
|
resolution: {integrity: sha512-yjEu2NwkHlXu0OARWoNhJlIjX09dRktiMQFsM678BAH/PEPVwctzL67+tvXqLCRQQvm3SDtki2saGO9hLlz68w==}
|
||||||
|
engines: {node: ^12.20.0 || >=14.13.1}
|
||||||
|
hasBin: true
|
||||||
|
|
||||||
terser-webpack-plugin@5.3.10:
|
terser-webpack-plugin@5.3.10:
|
||||||
resolution: {integrity: sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w==}
|
resolution: {integrity: sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w==}
|
||||||
engines: {node: '>= 10.13.0'}
|
engines: {node: '>= 10.13.0'}
|
||||||
@ -7789,7 +7838,7 @@ snapshots:
|
|||||||
'@strapi/design-system': 2.0.0-rc.24(@babel/runtime@7.26.0)(@codemirror/autocomplete@6.18.3(@codemirror/language@6.10.5)(@codemirror/state@6.4.1)(@codemirror/view@6.35.0)(@lezer/common@1.2.3))(@codemirror/language@6.10.5)(@codemirror/lint@6.8.4)(@codemirror/search@6.5.8)(@codemirror/state@6.4.1)(@codemirror/theme-one-dark@6.1.2)(@codemirror/view@6.35.0)(@strapi/icons@2.0.0-rc.24(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(styled-components@6.1.13(react-dom@18.3.1(react@18.3.1))(react@18.3.1)))(@types/react-dom@18.3.1)(@types/react@18.3.12)(codemirror@5.65.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(styled-components@6.1.13(react-dom@18.3.1(react@18.3.1))(react@18.3.1))
|
'@strapi/design-system': 2.0.0-rc.24(@babel/runtime@7.26.0)(@codemirror/autocomplete@6.18.3(@codemirror/language@6.10.5)(@codemirror/state@6.4.1)(@codemirror/view@6.35.0)(@lezer/common@1.2.3))(@codemirror/language@6.10.5)(@codemirror/lint@6.8.4)(@codemirror/search@6.5.8)(@codemirror/state@6.4.1)(@codemirror/theme-one-dark@6.1.2)(@codemirror/view@6.35.0)(@strapi/icons@2.0.0-rc.24(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(styled-components@6.1.13(react-dom@18.3.1(react@18.3.1))(react@18.3.1)))(@types/react-dom@18.3.1)(@types/react@18.3.12)(codemirror@5.65.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(styled-components@6.1.13(react-dom@18.3.1(react@18.3.1))(react@18.3.1))
|
||||||
'@strapi/icons': 2.0.0-rc.24(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(styled-components@6.1.13(react-dom@18.3.1(react@18.3.1))(react@18.3.1))
|
'@strapi/icons': 2.0.0-rc.24(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(styled-components@6.1.13(react-dom@18.3.1(react@18.3.1))(react@18.3.1))
|
||||||
'@strapi/permissions': 5.15.0
|
'@strapi/permissions': 5.15.0
|
||||||
'@strapi/types': 5.15.0(@types/node@20.17.9)(pg@8.8.0)(typescript@5.4.4)
|
'@strapi/types': 5.15.0(@types/node@20.17.9)(pg@8.8.0)(typescript@5.7.2)
|
||||||
'@strapi/typescript-utils': 5.15.0
|
'@strapi/typescript-utils': 5.15.0
|
||||||
'@strapi/utils': 5.15.0
|
'@strapi/utils': 5.15.0
|
||||||
'@testing-library/dom': 10.1.0
|
'@testing-library/dom': 10.1.0
|
||||||
@ -7982,7 +8031,7 @@ snapshots:
|
|||||||
'@strapi/database': 5.15.0(@types/node@20.17.9)(pg@8.8.0)
|
'@strapi/database': 5.15.0(@types/node@20.17.9)(pg@8.8.0)
|
||||||
'@strapi/design-system': 2.0.0-rc.24(@babel/runtime@7.26.0)(@codemirror/autocomplete@6.18.3(@codemirror/language@6.10.5)(@codemirror/state@6.4.1)(@codemirror/view@6.35.0)(@lezer/common@1.2.3))(@codemirror/language@6.10.5)(@codemirror/lint@6.8.4)(@codemirror/search@6.5.8)(@codemirror/state@6.4.1)(@codemirror/theme-one-dark@6.1.2)(@codemirror/view@6.35.0)(@strapi/icons@2.0.0-rc.24(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(styled-components@6.1.13(react-dom@18.3.1(react@18.3.1))(react@18.3.1)))(@types/react-dom@18.3.1)(@types/react@18.3.12)(codemirror@5.65.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(styled-components@6.1.13(react-dom@18.3.1(react@18.3.1))(react@18.3.1))
|
'@strapi/design-system': 2.0.0-rc.24(@babel/runtime@7.26.0)(@codemirror/autocomplete@6.18.3(@codemirror/language@6.10.5)(@codemirror/state@6.4.1)(@codemirror/view@6.35.0)(@lezer/common@1.2.3))(@codemirror/language@6.10.5)(@codemirror/lint@6.8.4)(@codemirror/search@6.5.8)(@codemirror/state@6.4.1)(@codemirror/theme-one-dark@6.1.2)(@codemirror/view@6.35.0)(@strapi/icons@2.0.0-rc.24(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(styled-components@6.1.13(react-dom@18.3.1(react@18.3.1))(react@18.3.1)))(@types/react-dom@18.3.1)(@types/react@18.3.12)(codemirror@5.65.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(styled-components@6.1.13(react-dom@18.3.1(react@18.3.1))(react@18.3.1))
|
||||||
'@strapi/icons': 2.0.0-rc.24(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(styled-components@6.1.13(react-dom@18.3.1(react@18.3.1))(react@18.3.1))
|
'@strapi/icons': 2.0.0-rc.24(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(styled-components@6.1.13(react-dom@18.3.1(react@18.3.1))(react@18.3.1))
|
||||||
'@strapi/types': 5.15.0(@types/node@20.17.9)(pg@8.8.0)(typescript@5.4.4)
|
'@strapi/types': 5.15.0(@types/node@20.17.9)(pg@8.8.0)(typescript@5.7.2)
|
||||||
'@strapi/utils': 5.15.0
|
'@strapi/utils': 5.15.0
|
||||||
date-fns: 2.30.0
|
date-fns: 2.30.0
|
||||||
date-fns-tz: 2.0.1(date-fns@2.30.0)
|
date-fns-tz: 2.0.1(date-fns@2.30.0)
|
||||||
@ -8075,7 +8124,7 @@ snapshots:
|
|||||||
'@strapi/generators': 5.15.0
|
'@strapi/generators': 5.15.0
|
||||||
'@strapi/logger': 5.15.0
|
'@strapi/logger': 5.15.0
|
||||||
'@strapi/permissions': 5.15.0
|
'@strapi/permissions': 5.15.0
|
||||||
'@strapi/types': 5.15.0(@types/node@20.17.9)(pg@8.8.0)(typescript@5.4.4)
|
'@strapi/types': 5.15.0(@types/node@20.17.9)(pg@8.8.0)(typescript@5.7.2)
|
||||||
'@strapi/typescript-utils': 5.15.0
|
'@strapi/typescript-utils': 5.15.0
|
||||||
'@strapi/utils': 5.15.0
|
'@strapi/utils': 5.15.0
|
||||||
bcryptjs: 2.4.3
|
bcryptjs: 2.4.3
|
||||||
@ -8525,7 +8574,7 @@ snapshots:
|
|||||||
'@strapi/logger': 5.15.0
|
'@strapi/logger': 5.15.0
|
||||||
'@strapi/permissions': 5.15.0
|
'@strapi/permissions': 5.15.0
|
||||||
'@strapi/review-workflows': 5.15.0(2imnoqd43gbalynv3yjuponlpy)
|
'@strapi/review-workflows': 5.15.0(2imnoqd43gbalynv3yjuponlpy)
|
||||||
'@strapi/types': 5.15.0(@types/node@20.17.9)(pg@8.8.0)(typescript@5.4.4)
|
'@strapi/types': 5.15.0(@types/node@20.17.9)(pg@8.8.0)(typescript@5.7.2)
|
||||||
'@strapi/typescript-utils': 5.15.0
|
'@strapi/typescript-utils': 5.15.0
|
||||||
'@strapi/upload': 5.15.0(6nrgkysfwt52tfycqocmy4s2kq)
|
'@strapi/upload': 5.15.0(6nrgkysfwt52tfycqocmy4s2kq)
|
||||||
'@strapi/utils': 5.15.0
|
'@strapi/utils': 5.15.0
|
||||||
@ -8627,34 +8676,6 @@ snapshots:
|
|||||||
- webpack-dev-server
|
- webpack-dev-server
|
||||||
- webpack-plugin-serve
|
- webpack-plugin-serve
|
||||||
|
|
||||||
'@strapi/types@5.15.0(@types/node@20.17.9)(pg@8.8.0)(typescript@5.4.4)':
|
|
||||||
dependencies:
|
|
||||||
'@casl/ability': 6.5.0
|
|
||||||
'@koa/cors': 5.0.0
|
|
||||||
'@koa/router': 12.0.2
|
|
||||||
'@strapi/database': 5.15.0(@types/node@20.17.9)(pg@8.8.0)
|
|
||||||
'@strapi/logger': 5.15.0
|
|
||||||
'@strapi/permissions': 5.15.0
|
|
||||||
'@strapi/utils': 5.15.0
|
|
||||||
commander: 8.3.0
|
|
||||||
koa: 2.16.1
|
|
||||||
koa-body: 6.0.1
|
|
||||||
node-schedule: 2.1.1
|
|
||||||
typedoc: 0.25.10(typescript@5.4.4)
|
|
||||||
typedoc-github-wiki-theme: 1.1.0(typedoc-plugin-markdown@3.17.1(typedoc@0.25.10(typescript@5.7.2)))(typedoc@0.25.10(typescript@5.7.2))
|
|
||||||
typedoc-plugin-markdown: 3.17.1(typedoc@0.25.10(typescript@5.7.2))
|
|
||||||
transitivePeerDependencies:
|
|
||||||
- '@types/node'
|
|
||||||
- better-sqlite3
|
|
||||||
- mysql
|
|
||||||
- mysql2
|
|
||||||
- pg
|
|
||||||
- pg-native
|
|
||||||
- sqlite3
|
|
||||||
- supports-color
|
|
||||||
- tedious
|
|
||||||
- typescript
|
|
||||||
|
|
||||||
'@strapi/types@5.15.0(@types/node@20.17.9)(pg@8.8.0)(typescript@5.7.2)':
|
'@strapi/types@5.15.0(@types/node@20.17.9)(pg@8.8.0)(typescript@5.7.2)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@casl/ability': 6.5.0
|
'@casl/ability': 6.5.0
|
||||||
@ -8845,6 +8866,8 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
defer-to-connect: 2.0.1
|
defer-to-connect: 2.0.1
|
||||||
|
|
||||||
|
'@telegraf/types@7.1.0': {}
|
||||||
|
|
||||||
'@testing-library/dom@10.1.0':
|
'@testing-library/dom@10.1.0':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/code-frame': 7.26.2
|
'@babel/code-frame': 7.26.2
|
||||||
@ -9223,6 +9246,10 @@ snapshots:
|
|||||||
|
|
||||||
'@xtuc/long@4.2.2': {}
|
'@xtuc/long@4.2.2': {}
|
||||||
|
|
||||||
|
abort-controller@3.0.0:
|
||||||
|
dependencies:
|
||||||
|
event-target-shim: 5.0.1
|
||||||
|
|
||||||
accepts@1.3.8:
|
accepts@1.3.8:
|
||||||
dependencies:
|
dependencies:
|
||||||
mime-types: 2.1.35
|
mime-types: 2.1.35
|
||||||
@ -9472,8 +9499,17 @@ snapshots:
|
|||||||
node-releases: 2.0.18
|
node-releases: 2.0.18
|
||||||
update-browserslist-db: 1.1.1(browserslist@4.24.2)
|
update-browserslist-db: 1.1.1(browserslist@4.24.2)
|
||||||
|
|
||||||
|
buffer-alloc-unsafe@1.1.0: {}
|
||||||
|
|
||||||
|
buffer-alloc@1.2.0:
|
||||||
|
dependencies:
|
||||||
|
buffer-alloc-unsafe: 1.1.0
|
||||||
|
buffer-fill: 1.0.0
|
||||||
|
|
||||||
buffer-equal-constant-time@1.0.1: {}
|
buffer-equal-constant-time@1.0.1: {}
|
||||||
|
|
||||||
|
buffer-fill@1.0.0: {}
|
||||||
|
|
||||||
buffer-from@1.1.2: {}
|
buffer-from@1.1.2: {}
|
||||||
|
|
||||||
buffer-writer@2.0.0: {}
|
buffer-writer@2.0.0: {}
|
||||||
@ -9908,6 +9944,8 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
'@babel/runtime': 7.26.0
|
'@babel/runtime': 7.26.0
|
||||||
|
|
||||||
|
dayjs@1.11.13: {}
|
||||||
|
|
||||||
debounce@1.2.1: {}
|
debounce@1.2.1: {}
|
||||||
|
|
||||||
debug@2.6.9:
|
debug@2.6.9:
|
||||||
@ -10262,6 +10300,8 @@ snapshots:
|
|||||||
|
|
||||||
etag@1.8.1: {}
|
etag@1.8.1: {}
|
||||||
|
|
||||||
|
event-target-shim@5.0.1: {}
|
||||||
|
|
||||||
events@3.3.0: {}
|
events@3.3.0: {}
|
||||||
|
|
||||||
eventsource@2.0.2: {}
|
eventsource@2.0.2: {}
|
||||||
@ -11623,6 +11663,8 @@ snapshots:
|
|||||||
|
|
||||||
mkdirp@3.0.1: {}
|
mkdirp@3.0.1: {}
|
||||||
|
|
||||||
|
mri@1.2.0: {}
|
||||||
|
|
||||||
mrmime@2.0.0: {}
|
mrmime@2.0.0: {}
|
||||||
|
|
||||||
ms@2.0.0: {}
|
ms@2.0.0: {}
|
||||||
@ -11899,6 +11941,8 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
aggregate-error: 4.0.1
|
aggregate-error: 4.0.1
|
||||||
|
|
||||||
|
p-timeout@4.1.0: {}
|
||||||
|
|
||||||
p-try@2.2.0: {}
|
p-try@2.2.0: {}
|
||||||
|
|
||||||
package-json-from-dist@1.0.1: {}
|
package-json-from-dist@1.0.1: {}
|
||||||
@ -12632,10 +12676,16 @@ snapshots:
|
|||||||
|
|
||||||
safe-buffer@5.2.1: {}
|
safe-buffer@5.2.1: {}
|
||||||
|
|
||||||
|
safe-compare@1.1.4:
|
||||||
|
dependencies:
|
||||||
|
buffer-alloc: 1.2.0
|
||||||
|
|
||||||
safe-stable-stringify@2.5.0: {}
|
safe-stable-stringify@2.5.0: {}
|
||||||
|
|
||||||
safer-buffer@2.1.2: {}
|
safer-buffer@2.1.2: {}
|
||||||
|
|
||||||
|
sandwich-stream@2.0.2: {}
|
||||||
|
|
||||||
sanitize-html@2.13.0:
|
sanitize-html@2.13.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
deepmerge: 4.3.1
|
deepmerge: 4.3.1
|
||||||
@ -13027,6 +13077,20 @@ snapshots:
|
|||||||
|
|
||||||
tarn@3.0.2: {}
|
tarn@3.0.2: {}
|
||||||
|
|
||||||
|
telegraf@4.16.3:
|
||||||
|
dependencies:
|
||||||
|
'@telegraf/types': 7.1.0
|
||||||
|
abort-controller: 3.0.0
|
||||||
|
debug: 4.3.7(supports-color@5.5.0)
|
||||||
|
mri: 1.2.0
|
||||||
|
node-fetch: 2.7.0
|
||||||
|
p-timeout: 4.1.0
|
||||||
|
safe-compare: 1.1.4
|
||||||
|
sandwich-stream: 2.0.2
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- encoding
|
||||||
|
- supports-color
|
||||||
|
|
||||||
terser-webpack-plugin@5.3.10(esbuild@0.25.5)(webpack@5.96.1(esbuild@0.25.5)):
|
terser-webpack-plugin@5.3.10(esbuild@0.25.5)(webpack@5.96.1(esbuild@0.25.5)):
|
||||||
dependencies:
|
dependencies:
|
||||||
'@jridgewell/trace-mapping': 0.3.25
|
'@jridgewell/trace-mapping': 0.3.25
|
||||||
@ -13142,14 +13206,6 @@ snapshots:
|
|||||||
handlebars: 4.7.8
|
handlebars: 4.7.8
|
||||||
typedoc: 0.25.10(typescript@5.7.2)
|
typedoc: 0.25.10(typescript@5.7.2)
|
||||||
|
|
||||||
typedoc@0.25.10(typescript@5.4.4):
|
|
||||||
dependencies:
|
|
||||||
lunr: 2.3.9
|
|
||||||
marked: 4.3.0
|
|
||||||
minimatch: 9.0.5
|
|
||||||
shiki: 0.14.7
|
|
||||||
typescript: 5.4.4
|
|
||||||
|
|
||||||
typedoc@0.25.10(typescript@5.7.2):
|
typedoc@0.25.10(typescript@5.7.2):
|
||||||
dependencies:
|
dependencies:
|
||||||
lunr: 2.3.9
|
lunr: 2.3.9
|
||||||
|
|||||||
@ -1,60 +0,0 @@
|
|||||||
{
|
|
||||||
"kind": "collectionType",
|
|
||||||
"collectionName": "blocks",
|
|
||||||
"info": {
|
|
||||||
"singularName": "block",
|
|
||||||
"pluralName": "blocks",
|
|
||||||
"displayName": "Block",
|
|
||||||
"description": ""
|
|
||||||
},
|
|
||||||
"options": {
|
|
||||||
"draftAndPublish": true
|
|
||||||
},
|
|
||||||
"pluginOptions": {},
|
|
||||||
"attributes": {
|
|
||||||
"datetime_start": {
|
|
||||||
"type": "datetime",
|
|
||||||
"required": true
|
|
||||||
},
|
|
||||||
"datetime_end": {
|
|
||||||
"type": "datetime",
|
|
||||||
"required": true
|
|
||||||
},
|
|
||||||
"state": {
|
|
||||||
"type": "enumeration",
|
|
||||||
"enum": [
|
|
||||||
"created",
|
|
||||||
"paid",
|
|
||||||
"deleted"
|
|
||||||
],
|
|
||||||
"default": "created"
|
|
||||||
},
|
|
||||||
"sessions_total": {
|
|
||||||
"type": "integer",
|
|
||||||
"default": 10,
|
|
||||||
"required": true
|
|
||||||
},
|
|
||||||
"sessions_completed": {
|
|
||||||
"type": "integer",
|
|
||||||
"default": 0
|
|
||||||
},
|
|
||||||
"master": {
|
|
||||||
"type": "relation",
|
|
||||||
"relation": "manyToOne",
|
|
||||||
"target": "api::customer.customer",
|
|
||||||
"inversedBy": "blocks"
|
|
||||||
},
|
|
||||||
"client": {
|
|
||||||
"type": "relation",
|
|
||||||
"relation": "manyToOne",
|
|
||||||
"target": "api::customer.customer",
|
|
||||||
"inversedBy": "blocks"
|
|
||||||
},
|
|
||||||
"orders": {
|
|
||||||
"type": "relation",
|
|
||||||
"relation": "oneToMany",
|
|
||||||
"target": "api::order.order",
|
|
||||||
"mappedBy": "block"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,7 +0,0 @@
|
|||||||
/**
|
|
||||||
* block controller
|
|
||||||
*/
|
|
||||||
|
|
||||||
import { factories } from '@strapi/strapi'
|
|
||||||
|
|
||||||
export default factories.createCoreController('api::block.block');
|
|
||||||
@ -1,7 +0,0 @@
|
|||||||
/**
|
|
||||||
* block router
|
|
||||||
*/
|
|
||||||
|
|
||||||
import { factories } from '@strapi/strapi';
|
|
||||||
|
|
||||||
export default factories.createCoreRouter('api::block.block');
|
|
||||||
@ -1,7 +0,0 @@
|
|||||||
/**
|
|
||||||
* block service
|
|
||||||
*/
|
|
||||||
|
|
||||||
import { factories } from '@strapi/strapi';
|
|
||||||
|
|
||||||
export default factories.createCoreService('api::block.block');
|
|
||||||
24
src/api/customer/content-types/customer-setting/schema.json
Normal file
24
src/api/customer/content-types/customer-setting/schema.json
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
{
|
||||||
|
"kind": "collectionType",
|
||||||
|
"collectionName": "customer_settings",
|
||||||
|
"info": {
|
||||||
|
"singularName": "customer-setting",
|
||||||
|
"pluralName": "customer-settings",
|
||||||
|
"displayName": "CustomerSettings"
|
||||||
|
},
|
||||||
|
"options": {
|
||||||
|
"draftAndPublish": false
|
||||||
|
},
|
||||||
|
"pluginOptions": {},
|
||||||
|
"attributes": {
|
||||||
|
"autoRenewSubscription": {
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
"customer": {
|
||||||
|
"type": "relation",
|
||||||
|
"relation": "oneToOne",
|
||||||
|
"target": "api::customer.customer",
|
||||||
|
"mappedBy": "customer_setting"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -14,47 +14,48 @@
|
|||||||
"attributes": {
|
"attributes": {
|
||||||
"name": {
|
"name": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
|
"maxLength": 100,
|
||||||
"required": true
|
"required": true
|
||||||
},
|
},
|
||||||
|
"surname": {
|
||||||
|
"type": "string",
|
||||||
|
"maxLength": 100,
|
||||||
|
"required": false
|
||||||
|
},
|
||||||
"telegramId": {
|
"telegramId": {
|
||||||
"type": "biginteger",
|
"type": "biginteger",
|
||||||
"unique": true
|
"unique": true
|
||||||
},
|
},
|
||||||
"phone": {
|
"phone": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"unique": true,
|
"maxLength": 20,
|
||||||
"required": true
|
"required": true,
|
||||||
|
"unique": true
|
||||||
},
|
},
|
||||||
"role": {
|
"role": {
|
||||||
"type": "enumeration",
|
"type": "enumeration",
|
||||||
|
"required": true,
|
||||||
"enum": [
|
"enum": [
|
||||||
"client",
|
"client",
|
||||||
"master"
|
"master"
|
||||||
],
|
]
|
||||||
"required": true
|
|
||||||
},
|
},
|
||||||
"active": {
|
"active": {
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"default": false,
|
"required": false,
|
||||||
"required": false
|
"default": false
|
||||||
},
|
},
|
||||||
"clients": {
|
"invited": {
|
||||||
"type": "relation",
|
"type": "relation",
|
||||||
"relation": "manyToMany",
|
"relation": "manyToMany",
|
||||||
"target": "api::customer.customer",
|
"target": "api::customer.customer",
|
||||||
"inversedBy": "masters"
|
"inversedBy": "invitedBy"
|
||||||
},
|
},
|
||||||
"masters": {
|
"invitedBy": {
|
||||||
"type": "relation",
|
"type": "relation",
|
||||||
"relation": "manyToMany",
|
"relation": "manyToMany",
|
||||||
"target": "api::customer.customer",
|
"target": "api::customer.customer",
|
||||||
"mappedBy": "clients"
|
"mappedBy": "invited"
|
||||||
},
|
|
||||||
"blocks": {
|
|
||||||
"type": "relation",
|
|
||||||
"relation": "oneToMany",
|
|
||||||
"target": "api::block.block",
|
|
||||||
"mappedBy": "client"
|
|
||||||
},
|
},
|
||||||
"slots": {
|
"slots": {
|
||||||
"type": "relation",
|
"type": "relation",
|
||||||
@ -76,6 +77,27 @@
|
|||||||
"relation": "oneToMany",
|
"relation": "oneToMany",
|
||||||
"target": "api::service.service",
|
"target": "api::service.service",
|
||||||
"mappedBy": "master"
|
"mappedBy": "master"
|
||||||
|
},
|
||||||
|
"subscriptions": {
|
||||||
|
"type": "relation",
|
||||||
|
"relation": "oneToMany",
|
||||||
|
"target": "api::subscription.subscription",
|
||||||
|
"mappedBy": "customer"
|
||||||
|
},
|
||||||
|
"bannedUntil": {
|
||||||
|
"type": "datetime"
|
||||||
|
},
|
||||||
|
"subscription_rewards": {
|
||||||
|
"type": "relation",
|
||||||
|
"relation": "oneToMany",
|
||||||
|
"target": "api::subscription-reward.subscription-reward",
|
||||||
|
"mappedBy": "owner"
|
||||||
|
},
|
||||||
|
"customer_setting": {
|
||||||
|
"type": "relation",
|
||||||
|
"relation": "oneToOne",
|
||||||
|
"target": "api::customer.customer-setting",
|
||||||
|
"inversedBy": "customer"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,189 +1,179 @@
|
|||||||
import { extractId } from '../../../../utils';
|
import { bot, extractId, dayjs } from '../../../../utils';
|
||||||
|
import { DEFAULT_TZ } from '../../../../constants';
|
||||||
|
|
||||||
const ERR_MISSING_TIME = 'Не указано время';
|
const STATE_MAP: Record<State, string> = {
|
||||||
const ERR_INVALID_TIME = 'Некорректное время';
|
approved: 'Подтверждено',
|
||||||
const ERR_OVERLAPPING_TIME = 'Время пересекается с другими заказами';
|
cancelled: 'Отменено',
|
||||||
const ERR_INACTIVE_CLIENT = 'Клиент не активен';
|
cancelling: 'Отменяется',
|
||||||
const ERR_INACTIVE_MASTER = 'Мастер не активен';
|
completed: 'Завершено',
|
||||||
const ERR_SLOT_CLOSED = 'Слот закрыт';
|
created: 'Создано',
|
||||||
const ERR_INVALID_CLIENT = 'Некорректный клиент';
|
scheduled: 'Запланировано',
|
||||||
const ERR_INVALID_MASTER = 'Некорректный мастер';
|
};
|
||||||
const ERR_MISSING_CLIENT = 'Не указан клиент';
|
|
||||||
const ERR_MISSING_SLOT = 'Не указан слот';
|
|
||||||
const ERR_MISSING_SERVICE = 'Не указан сервис';
|
|
||||||
|
|
||||||
function timeToDate(time: string) {
|
const EMOJI_MAP: Record<State, string> = {
|
||||||
return new Date(`1970-01-01T${time}Z`);
|
approved: '✅',
|
||||||
}
|
cancelled: '❌',
|
||||||
|
cancelling: '🟠',
|
||||||
|
completed: '🏁',
|
||||||
|
created: '📝',
|
||||||
|
scheduled: '📅',
|
||||||
|
};
|
||||||
|
|
||||||
export default {
|
type State =
|
||||||
async beforeCreate(event) {
|
| 'approved'
|
||||||
const { data } = event.params;
|
| 'cancelled'
|
||||||
const { time_start, time_end, client, services } = data;
|
| 'cancelling'
|
||||||
const clientId = extractId(client);
|
| 'completed'
|
||||||
const slotId = extractId(data.slot);
|
| 'created'
|
||||||
|
| 'scheduled';
|
||||||
|
|
||||||
// Проверка наличия обязательных полей
|
type Order = {
|
||||||
if (!slotId) throw new Error(ERR_MISSING_SLOT);
|
id: number;
|
||||||
if (!clientId) throw new Error(ERR_MISSING_CLIENT);
|
documentId: string;
|
||||||
if (!extractId(services)) throw new Error(ERR_MISSING_SERVICE);
|
state: State;
|
||||||
|
order_number: number;
|
||||||
|
createdAt: string;
|
||||||
|
updatedAt: string;
|
||||||
|
publishedAt: any;
|
||||||
|
locale: any;
|
||||||
|
datetime_start: string;
|
||||||
|
datetime_end: string;
|
||||||
|
};
|
||||||
|
|
||||||
// Проверка корректности времени заказа.
|
async function sendTelegramNotification(orderEntity: Order, isUpdate = false) {
|
||||||
if (!time_start || !time_end) {
|
try {
|
||||||
throw new Error(ERR_MISSING_TIME);
|
const order = await strapi.db.query('api::order.order').findOne({
|
||||||
}
|
where: { id: orderEntity.id },
|
||||||
if (timeToDate(time_start) >= timeToDate(time_end)) {
|
populate: ['client', 'slot', 'services'],
|
||||||
throw new Error(ERR_INVALID_TIME);
|
});
|
||||||
}
|
|
||||||
|
|
||||||
// Получаем слот
|
if (!order) throw new Error('Order not found');
|
||||||
|
|
||||||
|
const slotId = extractId(order.slot);
|
||||||
const slot = await strapi.db.query('api::slot.slot').findOne({
|
const slot = await strapi.db.query('api::slot.slot').findOne({
|
||||||
where: { id: slotId },
|
where: { id: slotId },
|
||||||
populate: ['master'],
|
populate: ['master'],
|
||||||
});
|
});
|
||||||
if (!slot) throw new Error(ERR_MISSING_SLOT);
|
|
||||||
|
|
||||||
// 1. Слот не должен быть закрыт
|
if (!slot) throw new Error('Slot not found');
|
||||||
if (slot.state === 'closed') {
|
|
||||||
throw new Error(ERR_SLOT_CLOSED);
|
const clientTelegramId = order.client?.telegramId;
|
||||||
|
const masterTelegramId = slot.master?.telegramId;
|
||||||
|
|
||||||
|
if (!masterTelegramId) {
|
||||||
|
console.warn('Master telegram ID not found');
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Получаем клиента
|
const state = orderEntity.state;
|
||||||
const clientEntity = await strapi.db
|
const emojiForState = EMOJI_MAP[state] || '';
|
||||||
.query('api::customer.customer')
|
const stateLabel = STATE_MAP[state] || state;
|
||||||
.findOne({
|
|
||||||
where: { id: clientId },
|
|
||||||
populate: { masters: true },
|
|
||||||
});
|
|
||||||
if (!clientEntity) throw new Error(ERR_MISSING_CLIENT);
|
|
||||||
|
|
||||||
// Проверка активности клиента
|
// Эмодзи в заголовке: карандаш при обновлении, флаг для завершенных, иначе эмодзи статуса
|
||||||
if (!clientEntity.active) {
|
const headingEmoji = isUpdate
|
||||||
throw new Error(ERR_INACTIVE_CLIENT);
|
? (state === 'completed' ? '🏁' : '✏️')
|
||||||
}
|
: emojiForState;
|
||||||
|
|
||||||
// Получаем мастера слота
|
let heading = '';
|
||||||
const slotMaster = slot.master;
|
|
||||||
if (!slotMaster) throw new Error(ERR_INVALID_MASTER);
|
|
||||||
if (!slotMaster.active || slotMaster.role !== 'master') {
|
|
||||||
throw new Error(ERR_INACTIVE_MASTER);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2. Проверка ролей и связей
|
if (isUpdate) {
|
||||||
const isClientMaster = clientEntity.role === 'master';
|
// Специальная обработка для завершенных записей
|
||||||
const slotMasterId = slotMaster.id;
|
if (state === 'completed') {
|
||||||
|
heading = `${headingEmoji} <b>Запись завершена</b>`;
|
||||||
if (!isClientMaster) {
|
} else {
|
||||||
// Клиент не должен быть мастером слота
|
heading = `${headingEmoji} <b>Запись изменена</b>`;
|
||||||
if (clientEntity.id === slotMasterId) {
|
|
||||||
throw new Error(ERR_INVALID_CLIENT);
|
|
||||||
}
|
|
||||||
// Клиент должен быть в списке клиентов мастера
|
|
||||||
const masters = clientEntity.masters?.map(m => m.id) || [];
|
|
||||||
if (!masters.includes(slotMasterId)) {
|
|
||||||
throw new Error(ERR_INVALID_MASTER);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Мастер не может записать другого мастера
|
const isApproved = state === 'approved';
|
||||||
if (slotMasterId !== clientEntity.id) {
|
const creationText = isApproved
|
||||||
throw new Error(ERR_INVALID_MASTER);
|
? `Запись создана и подтверждена!`
|
||||||
}
|
: `Запись создана!`;
|
||||||
|
heading = `${headingEmoji} <b>${creationText}</b>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Проверка пересечений заказов по времени.
|
const date = dayjs
|
||||||
const overlappingEntities = await strapi.db
|
.utc(orderEntity.datetime_start)
|
||||||
.query('api::order.order')
|
.tz(DEFAULT_TZ)
|
||||||
.findMany({
|
.format('D MMMM YYYY');
|
||||||
where: {
|
const timeStartString = dayjs
|
||||||
documentId: { $ne: data.documentId },
|
.utc(orderEntity.datetime_start)
|
||||||
time_start: { $lt: time_end },
|
.tz(DEFAULT_TZ)
|
||||||
time_end: { $gt: time_start },
|
.format('HH:mm');
|
||||||
slot: {
|
const timeEndString = dayjs
|
||||||
id: { $eq: slotId },
|
.utc(orderEntity.datetime_end)
|
||||||
},
|
.tz(DEFAULT_TZ)
|
||||||
state: {
|
.format('HH:mm');
|
||||||
$notIn: ['cancelled', 'completed'],
|
|
||||||
},
|
const clientName = order.client?.name || '-';
|
||||||
},
|
const masterName = slot.master?.name || '-';
|
||||||
populate: ['slot'],
|
|
||||||
|
// Формируем список всех услуг и вычисляем общую стоимость
|
||||||
|
let servicesList = '-';
|
||||||
|
let totalPrice = 0;
|
||||||
|
|
||||||
|
if (order.services?.length) {
|
||||||
|
servicesList = order.services.map(service => service.name).join(', ');
|
||||||
|
|
||||||
|
// Вычисляем общую стоимость
|
||||||
|
totalPrice = order.services.reduce((sum, service) => {
|
||||||
|
return sum + (service.price || 0);
|
||||||
|
}, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Форматируем цену для отображения
|
||||||
|
const priceText = totalPrice > 0 ? `${totalPrice.toLocaleString('ru-RU')} ₽` : 'Не указана';
|
||||||
|
|
||||||
|
const messageForMaster = `${heading}
|
||||||
|
<b>Дата:</b> ${date}
|
||||||
|
<b>Время:</b> ${timeStartString} - ${timeEndString}
|
||||||
|
<b>Клиент:</b> ${clientName}
|
||||||
|
<b>Услуги:</b> ${servicesList}
|
||||||
|
<b>Стоимость:</b> ${priceText}
|
||||||
|
<b>Статус:</b> ${emojiForState} ${stateLabel}`;
|
||||||
|
|
||||||
|
const messageForClient = `${heading}
|
||||||
|
<b>Дата:</b> ${date}
|
||||||
|
<b>Время:</b> ${timeStartString} - ${timeEndString}
|
||||||
|
<b>Мастер:</b> ${masterName}
|
||||||
|
<b>Услуги:</b> ${servicesList}
|
||||||
|
<b>Стоимость:</b> ${priceText}
|
||||||
|
<b>Статус:</b> ${emojiForState} ${stateLabel}`;
|
||||||
|
|
||||||
|
if (masterTelegramId) {
|
||||||
|
await bot.telegram.sendMessage(masterTelegramId, messageForMaster, {
|
||||||
|
parse_mode: 'HTML',
|
||||||
});
|
});
|
||||||
|
|
||||||
if (overlappingEntities.length > 0) {
|
|
||||||
throw new Error(ERR_OVERLAPPING_TIME);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (clientTelegramId) {
|
||||||
|
await bot.telegram.sendMessage(clientTelegramId, messageForClient, {
|
||||||
|
parse_mode: 'HTML',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('❌ Error sending Telegram notification:', error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default {
|
||||||
|
async afterCreate({ result }) {
|
||||||
|
const createdEntity = result as Order;
|
||||||
|
|
||||||
|
if (!createdEntity.publishedAt) return;
|
||||||
|
|
||||||
|
const isUpdate = createdEntity.createdAt !== createdEntity.updatedAt;
|
||||||
|
|
||||||
|
await sendTelegramNotification(createdEntity, isUpdate);
|
||||||
},
|
},
|
||||||
|
|
||||||
async beforeUpdate(event) {
|
async afterUpdate({ result, params }) {
|
||||||
const { data, where } = event.params;
|
const updatedEntity = result as Order;
|
||||||
const { id: entityId } = where;
|
|
||||||
const { time_start, time_end, state } = data;
|
|
||||||
|
|
||||||
const existingOrder = await strapi.db.query('api::order.order').findOne({
|
if (!updatedEntity.publishedAt) return;
|
||||||
where: { id: entityId },
|
|
||||||
select: ['documentId', 'time_start', 'time_end'],
|
|
||||||
populate: ['slot', 'client'],
|
|
||||||
});
|
|
||||||
|
|
||||||
if (state && !time_start && !time_end) {
|
const previousState = params?.data?.state;
|
||||||
if (state === 'completed') {
|
if (!previousState || previousState === updatedEntity.state) return;
|
||||||
const clientId = extractId(existingOrder.client);
|
|
||||||
|
|
||||||
const lastOrder = await strapi.db.query('api::order.order').findMany({
|
await sendTelegramNotification(updatedEntity, true);
|
||||||
where: {
|
|
||||||
client: {
|
|
||||||
id: clientId,
|
|
||||||
},
|
|
||||||
state: 'completed',
|
|
||||||
},
|
|
||||||
orderBy: { order_number: 'desc' },
|
|
||||||
limit: 1,
|
|
||||||
});
|
|
||||||
|
|
||||||
const lastOrderNumber =
|
|
||||||
lastOrder.length > 0 ? lastOrder[0].order_number : 0;
|
|
||||||
data.order_number = lastOrderNumber + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (
|
|
||||||
existingOrder.time_start === time_start &&
|
|
||||||
existingOrder.time_end === time_end
|
|
||||||
) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!time_start || !time_end) {
|
|
||||||
throw new Error(ERR_INVALID_TIME);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (timeToDate(time_start) >= timeToDate(time_end)) {
|
|
||||||
throw new Error(ERR_INVALID_TIME);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!existingOrder || !existingOrder.slot) {
|
|
||||||
throw new Error('Существующий заказ или слот не найден');
|
|
||||||
}
|
|
||||||
|
|
||||||
const slotId = existingOrder.slot.documentId;
|
|
||||||
|
|
||||||
const overlappingEntities = await strapi.db
|
|
||||||
.query('api::order.order')
|
|
||||||
.findMany({
|
|
||||||
where: {
|
|
||||||
id: { $ne: entityId },
|
|
||||||
time_start: { $lt: time_end },
|
|
||||||
time_end: { $gt: time_start },
|
|
||||||
slot: {
|
|
||||||
documentId: { $eq: slotId },
|
|
||||||
},
|
|
||||||
},
|
|
||||||
populate: ['slot'],
|
|
||||||
});
|
|
||||||
|
|
||||||
if (overlappingEntities.length > 0) {
|
|
||||||
throw new Error(ERR_OVERLAPPING_TIME);
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@ -24,24 +24,12 @@
|
|||||||
"cancelled"
|
"cancelled"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"price": {
|
|
||||||
"type": "integer"
|
|
||||||
},
|
|
||||||
"service_description": {
|
|
||||||
"type": "text"
|
|
||||||
},
|
|
||||||
"client": {
|
"client": {
|
||||||
"type": "relation",
|
"type": "relation",
|
||||||
"relation": "manyToOne",
|
"relation": "manyToOne",
|
||||||
"target": "api::customer.customer",
|
"target": "api::customer.customer",
|
||||||
"inversedBy": "orders"
|
"inversedBy": "orders"
|
||||||
},
|
},
|
||||||
"block": {
|
|
||||||
"type": "relation",
|
|
||||||
"relation": "manyToOne",
|
|
||||||
"target": "api::block.block",
|
|
||||||
"inversedBy": "orders"
|
|
||||||
},
|
|
||||||
"order_number": {
|
"order_number": {
|
||||||
"type": "integer"
|
"type": "integer"
|
||||||
},
|
},
|
||||||
@ -51,17 +39,19 @@
|
|||||||
"target": "api::slot.slot",
|
"target": "api::slot.slot",
|
||||||
"inversedBy": "orders"
|
"inversedBy": "orders"
|
||||||
},
|
},
|
||||||
"time_start": {
|
|
||||||
"type": "time"
|
|
||||||
},
|
|
||||||
"time_end": {
|
|
||||||
"type": "time"
|
|
||||||
},
|
|
||||||
"services": {
|
"services": {
|
||||||
"type": "relation",
|
"type": "relation",
|
||||||
"relation": "manyToMany",
|
"relation": "manyToMany",
|
||||||
"target": "api::service.service",
|
"target": "api::service.service",
|
||||||
"inversedBy": "orders"
|
"inversedBy": "orders"
|
||||||
|
},
|
||||||
|
"datetime_start": {
|
||||||
|
"type": "datetime",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
"datetime_end": {
|
||||||
|
"type": "datetime",
|
||||||
|
"required": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,7 +4,7 @@
|
|||||||
"info": {
|
"info": {
|
||||||
"singularName": "service",
|
"singularName": "service",
|
||||||
"pluralName": "services",
|
"pluralName": "services",
|
||||||
"displayName": "service",
|
"displayName": "Service",
|
||||||
"description": ""
|
"description": ""
|
||||||
},
|
},
|
||||||
"options": {
|
"options": {
|
||||||
@ -13,7 +13,9 @@
|
|||||||
"pluginOptions": {},
|
"pluginOptions": {},
|
||||||
"attributes": {
|
"attributes": {
|
||||||
"name": {
|
"name": {
|
||||||
"type": "string"
|
"type": "string",
|
||||||
|
"maxLength": 100,
|
||||||
|
"required": true
|
||||||
},
|
},
|
||||||
"orders": {
|
"orders": {
|
||||||
"type": "relation",
|
"type": "relation",
|
||||||
@ -31,6 +33,17 @@
|
|||||||
"type": "time",
|
"type": "time",
|
||||||
"required": true,
|
"required": true,
|
||||||
"default": "01:00:00.000"
|
"default": "01:00:00.000"
|
||||||
|
},
|
||||||
|
"active": {
|
||||||
|
"type": "boolean",
|
||||||
|
"default": false
|
||||||
|
},
|
||||||
|
"price": {
|
||||||
|
"type": "decimal",
|
||||||
|
"min": 1
|
||||||
|
},
|
||||||
|
"description": {
|
||||||
|
"type": "text"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,20 +0,0 @@
|
|||||||
{
|
|
||||||
"kind": "collectionType",
|
|
||||||
"collectionName": "settings",
|
|
||||||
"info": {
|
|
||||||
"singularName": "setting",
|
|
||||||
"pluralName": "settings",
|
|
||||||
"displayName": "Setting",
|
|
||||||
"description": ""
|
|
||||||
},
|
|
||||||
"options": {
|
|
||||||
"draftAndPublish": true
|
|
||||||
},
|
|
||||||
"pluginOptions": {},
|
|
||||||
"attributes": {
|
|
||||||
"recording_by_blocks": {
|
|
||||||
"type": "boolean",
|
|
||||||
"default": false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,7 +0,0 @@
|
|||||||
/**
|
|
||||||
* setting controller
|
|
||||||
*/
|
|
||||||
|
|
||||||
import { factories } from '@strapi/strapi'
|
|
||||||
|
|
||||||
export default factories.createCoreController('api::setting.setting');
|
|
||||||
@ -1,7 +0,0 @@
|
|||||||
/**
|
|
||||||
* setting router
|
|
||||||
*/
|
|
||||||
|
|
||||||
import { factories } from '@strapi/strapi';
|
|
||||||
|
|
||||||
export default factories.createCoreRouter('api::setting.setting');
|
|
||||||
@ -1,7 +0,0 @@
|
|||||||
/**
|
|
||||||
* setting service
|
|
||||||
*/
|
|
||||||
|
|
||||||
import { factories } from '@strapi/strapi';
|
|
||||||
|
|
||||||
export default factories.createCoreService('api::setting.setting');
|
|
||||||
@ -1,152 +0,0 @@
|
|||||||
import { extractId } from '../../../../utils';
|
|
||||||
|
|
||||||
const ERR_INVALID_TIME = 'Некорректное время';
|
|
||||||
const ERR_OVERLAPPING_TIME = 'Время пересекается с другими слотами';
|
|
||||||
const ERR_FORBIDDEN_SLOT_STATUS =
|
|
||||||
'Нельзя менять время слота, если есть связанные заказы';
|
|
||||||
|
|
||||||
const FORBIDDEN_ORDER_STATES = [
|
|
||||||
'scheduled',
|
|
||||||
'approved',
|
|
||||||
'completed',
|
|
||||||
'cancelling',
|
|
||||||
];
|
|
||||||
|
|
||||||
const ERR_INACTIVE_MASTER = 'Мастер не активен';
|
|
||||||
const ERR_INVALID_MASTER = 'Некорректный мастер';
|
|
||||||
const ERR_PAST_SLOT = 'Нельзя создать слот в прошлом';
|
|
||||||
const ERR_SLOT_HAS_ORDERS = 'Нельзя удалить слот с активными заказами';
|
|
||||||
|
|
||||||
function timeToDate(date, time) {
|
|
||||||
return new Date(`${date}T${time}:00Z`);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default {
|
|
||||||
async beforeCreate(event) {
|
|
||||||
const { data } = event.params;
|
|
||||||
const { master, date, time_start, time_end } = data;
|
|
||||||
|
|
||||||
// Проверка, что мастер существует и активен
|
|
||||||
const masterId = extractId(master);
|
|
||||||
const masterEntity = await strapi.db
|
|
||||||
.query('api::customer.customer')
|
|
||||||
.findOne({
|
|
||||||
where: { id: masterId },
|
|
||||||
});
|
|
||||||
if (!masterEntity) throw new Error(ERR_INVALID_MASTER);
|
|
||||||
if (!masterEntity.active || masterEntity.role !== 'master') {
|
|
||||||
throw new Error(ERR_INACTIVE_MASTER);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Проверка, что слот не создаётся в прошлом
|
|
||||||
if (date && time_start) {
|
|
||||||
const slotDate = timeToDate(date, time_start);
|
|
||||||
if (slotDate < new Date()) {
|
|
||||||
throw new Error(ERR_PAST_SLOT);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// --- Существующие проверки времени и пересечений ---
|
|
||||||
if (!time_start || !time_end) {
|
|
||||||
throw new Error('Некорректное время');
|
|
||||||
}
|
|
||||||
if (timeToDate(date, time_start) >= timeToDate(date, time_end)) {
|
|
||||||
throw new Error('Некорректное время');
|
|
||||||
}
|
|
||||||
const overlappingEntities = await strapi.db
|
|
||||||
.query('api::slot.slot')
|
|
||||||
.findMany({
|
|
||||||
where: {
|
|
||||||
date,
|
|
||||||
documentId: { $ne: data.documentId },
|
|
||||||
time_start: { $lt: time_end },
|
|
||||||
time_end: { $gt: time_start },
|
|
||||||
master: masterId,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
if (overlappingEntities.length > 0) {
|
|
||||||
throw new Error('Время пересекается с другими слотами');
|
|
||||||
}
|
|
||||||
},
|
|
||||||
async beforeUpdate(event) {
|
|
||||||
const { data, where } = event.params;
|
|
||||||
const { id: entityId } = where;
|
|
||||||
|
|
||||||
// Если меняется хотя бы одно из полей времени или дата
|
|
||||||
const isTimeChange =
|
|
||||||
'time_start' in data || 'time_end' in data || 'date' in data;
|
|
||||||
|
|
||||||
if (isTimeChange) {
|
|
||||||
let date = data.date;
|
|
||||||
let time_start = data.time_start;
|
|
||||||
let time_end = data.time_end;
|
|
||||||
|
|
||||||
// Подтянуть недостающие значения из существующего слота
|
|
||||||
const existingSlot = await strapi.db.query('api::slot.slot').findOne({
|
|
||||||
where: { id: entityId },
|
|
||||||
select: ['date', 'time_start', 'time_end'],
|
|
||||||
});
|
|
||||||
if (!date) date = existingSlot?.date;
|
|
||||||
if (!time_start) time_start = existingSlot?.time_start;
|
|
||||||
if (!time_end) time_end = existingSlot?.time_end;
|
|
||||||
|
|
||||||
// Проверка: оба времени должны быть определены
|
|
||||||
if (!time_start || !time_end) {
|
|
||||||
throw new Error(ERR_INVALID_TIME);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Проверка валидности времени
|
|
||||||
if (timeToDate(date, time_start) >= timeToDate(date, time_end)) {
|
|
||||||
throw new Error(ERR_INVALID_TIME);
|
|
||||||
}
|
|
||||||
|
|
||||||
const existingEntity = await strapi.db.query('api::slot.slot').findOne({
|
|
||||||
where: { id: entityId },
|
|
||||||
select: ['date', 'documentId'],
|
|
||||||
populate: ['orders'],
|
|
||||||
});
|
|
||||||
|
|
||||||
const orders = existingEntity?.orders;
|
|
||||||
|
|
||||||
if (
|
|
||||||
orders?.length > 0 &&
|
|
||||||
orders?.some(order => FORBIDDEN_ORDER_STATES.includes(order.state))
|
|
||||||
) {
|
|
||||||
throw new Error(ERR_FORBIDDEN_SLOT_STATUS);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!existingEntity) {
|
|
||||||
throw new Error('Запись не найдена');
|
|
||||||
}
|
|
||||||
|
|
||||||
const { documentId } = existingEntity;
|
|
||||||
|
|
||||||
const overlappingEntities = await strapi.db
|
|
||||||
.query('api::slot.slot')
|
|
||||||
.findMany({
|
|
||||||
where: {
|
|
||||||
date,
|
|
||||||
id: { $ne: entityId },
|
|
||||||
documentId: { $ne: documentId },
|
|
||||||
time_start: { $lt: time_end },
|
|
||||||
time_end: { $gt: time_start },
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
if (overlappingEntities.length > 0) {
|
|
||||||
throw new Error(ERR_OVERLAPPING_TIME);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
async beforeDelete(event) {
|
|
||||||
const { where } = event.params;
|
|
||||||
const slotId = where.id;
|
|
||||||
const slot = await strapi.db.query('api::slot.slot').findOne({
|
|
||||||
where: { id: slotId },
|
|
||||||
populate: ['orders'],
|
|
||||||
});
|
|
||||||
if (slot?.orders?.length) {
|
|
||||||
throw new Error(ERR_SLOT_HAS_ORDERS);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
};
|
|
||||||
@ -12,14 +12,6 @@
|
|||||||
},
|
},
|
||||||
"pluginOptions": {},
|
"pluginOptions": {},
|
||||||
"attributes": {
|
"attributes": {
|
||||||
"time_start": {
|
|
||||||
"type": "time",
|
|
||||||
"required": true
|
|
||||||
},
|
|
||||||
"time_end": {
|
|
||||||
"type": "time",
|
|
||||||
"required": true
|
|
||||||
},
|
|
||||||
"state": {
|
"state": {
|
||||||
"type": "enumeration",
|
"type": "enumeration",
|
||||||
"enum": [
|
"enum": [
|
||||||
@ -40,8 +32,13 @@
|
|||||||
"target": "api::customer.customer",
|
"target": "api::customer.customer",
|
||||||
"inversedBy": "slots"
|
"inversedBy": "slots"
|
||||||
},
|
},
|
||||||
"date": {
|
"datetime_end": {
|
||||||
"type": "date"
|
"type": "datetime",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
"datetime_start": {
|
||||||
|
"type": "datetime",
|
||||||
|
"required": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,67 @@
|
|||||||
|
{
|
||||||
|
"kind": "collectionType",
|
||||||
|
"collectionName": "subscription_histories",
|
||||||
|
"info": {
|
||||||
|
"singularName": "subscription-history",
|
||||||
|
"pluralName": "subscription-histories",
|
||||||
|
"displayName": "SubscriptionHistory"
|
||||||
|
},
|
||||||
|
"options": {
|
||||||
|
"draftAndPublish": true
|
||||||
|
},
|
||||||
|
"pluginOptions": {},
|
||||||
|
"attributes": {
|
||||||
|
"subscription": {
|
||||||
|
"type": "relation",
|
||||||
|
"relation": "oneToOne",
|
||||||
|
"target": "api::subscription.subscription",
|
||||||
|
"mappedBy": "subscription_history"
|
||||||
|
},
|
||||||
|
"subscription_price": {
|
||||||
|
"type": "relation",
|
||||||
|
"relation": "oneToOne",
|
||||||
|
"target": "api::subscription-price.subscription-price"
|
||||||
|
},
|
||||||
|
"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",
|
||||||
|
"trial",
|
||||||
|
"reward",
|
||||||
|
"admin",
|
||||||
|
"renewal"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"description": {
|
||||||
|
"type": "text"
|
||||||
|
},
|
||||||
|
"period": {
|
||||||
|
"type": "string",
|
||||||
|
"maxLength": 20
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,7 @@
|
|||||||
|
/**
|
||||||
|
* subscription-history controller
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { factories } from '@strapi/strapi'
|
||||||
|
|
||||||
|
export default factories.createCoreController('api::subscription-history.subscription-history');
|
||||||
@ -0,0 +1,7 @@
|
|||||||
|
/**
|
||||||
|
* subscription-history router
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { factories } from '@strapi/strapi';
|
||||||
|
|
||||||
|
export default factories.createCoreRouter('api::subscription-history.subscription-history');
|
||||||
@ -0,0 +1,7 @@
|
|||||||
|
/**
|
||||||
|
* subscription-history service
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { factories } from '@strapi/strapi';
|
||||||
|
|
||||||
|
export default factories.createCoreService('api::subscription-history.subscription-history');
|
||||||
@ -0,0 +1,48 @@
|
|||||||
|
{
|
||||||
|
"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",
|
||||||
|
"day",
|
||||||
|
"week",
|
||||||
|
"month",
|
||||||
|
"half_year",
|
||||||
|
"year"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"amount": {
|
||||||
|
"type": "decimal",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
"currency": {
|
||||||
|
"type": "string",
|
||||||
|
"default": "RUB",
|
||||||
|
"required": false
|
||||||
|
},
|
||||||
|
"active": {
|
||||||
|
"type": "boolean",
|
||||||
|
"required": false,
|
||||||
|
"default": true
|
||||||
|
},
|
||||||
|
"description": {
|
||||||
|
"type": "text"
|
||||||
|
},
|
||||||
|
"days": {
|
||||||
|
"type": "integer",
|
||||||
|
"required": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,7 @@
|
|||||||
|
/**
|
||||||
|
* subscription-price controller
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { factories } from '@strapi/strapi'
|
||||||
|
|
||||||
|
export default factories.createCoreController('api::subscription-price.subscription-price');
|
||||||
7
src/api/subscription-price/routes/subscription-price.ts
Normal file
7
src/api/subscription-price/routes/subscription-price.ts
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
/**
|
||||||
|
* subscription-price router
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { factories } from '@strapi/strapi';
|
||||||
|
|
||||||
|
export default factories.createCoreRouter('api::subscription-price.subscription-price');
|
||||||
@ -0,0 +1,7 @@
|
|||||||
|
/**
|
||||||
|
* subscription-price service
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { factories } from '@strapi/strapi';
|
||||||
|
|
||||||
|
export default factories.createCoreService('api::subscription-price.subscription-price');
|
||||||
@ -0,0 +1,47 @@
|
|||||||
|
{
|
||||||
|
"kind": "collectionType",
|
||||||
|
"collectionName": "subscription_rewards",
|
||||||
|
"info": {
|
||||||
|
"singularName": "subscription-reward",
|
||||||
|
"pluralName": "subscription-rewards",
|
||||||
|
"displayName": "SubscriptionReward"
|
||||||
|
},
|
||||||
|
"options": {
|
||||||
|
"draftAndPublish": true
|
||||||
|
},
|
||||||
|
"pluginOptions": {},
|
||||||
|
"attributes": {
|
||||||
|
"activated": {
|
||||||
|
"type": "boolean",
|
||||||
|
"default": false
|
||||||
|
},
|
||||||
|
"owner": {
|
||||||
|
"type": "relation",
|
||||||
|
"relation": "manyToOne",
|
||||||
|
"target": "api::customer.customer",
|
||||||
|
"inversedBy": "subscription_rewards"
|
||||||
|
},
|
||||||
|
"invited": {
|
||||||
|
"type": "relation",
|
||||||
|
"relation": "oneToOne",
|
||||||
|
"target": "api::customer.customer"
|
||||||
|
},
|
||||||
|
"days": {
|
||||||
|
"type": "integer",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
"expiresAt": {
|
||||||
|
"type": "datetime",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
"description": {
|
||||||
|
"type": "text"
|
||||||
|
},
|
||||||
|
"subscription": {
|
||||||
|
"type": "relation",
|
||||||
|
"relation": "manyToOne",
|
||||||
|
"target": "api::subscription.subscription",
|
||||||
|
"inversedBy": "subscription_rewards"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,7 @@
|
|||||||
|
/**
|
||||||
|
* subscription-reward controller
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { factories } from '@strapi/strapi'
|
||||||
|
|
||||||
|
export default factories.createCoreController('api::subscription-reward.subscription-reward');
|
||||||
@ -0,0 +1,7 @@
|
|||||||
|
/**
|
||||||
|
* subscription-reward router
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { factories } from '@strapi/strapi';
|
||||||
|
|
||||||
|
export default factories.createCoreRouter('api::subscription-reward.subscription-reward');
|
||||||
@ -0,0 +1,7 @@
|
|||||||
|
/**
|
||||||
|
* subscription-reward service
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { factories } from '@strapi/strapi';
|
||||||
|
|
||||||
|
export default factories.createCoreService('api::subscription-reward.subscription-reward');
|
||||||
@ -0,0 +1,29 @@
|
|||||||
|
{
|
||||||
|
"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": 20
|
||||||
|
},
|
||||||
|
"referralRewardDays": {
|
||||||
|
"type": "integer",
|
||||||
|
"required": true,
|
||||||
|
"default": 1
|
||||||
|
},
|
||||||
|
"proEnabled": {
|
||||||
|
"type": "boolean",
|
||||||
|
"default": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,7 @@
|
|||||||
|
/**
|
||||||
|
* subscription-setting controller
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { factories } from '@strapi/strapi'
|
||||||
|
|
||||||
|
export default factories.createCoreController('api::subscription-setting.subscription-setting');
|
||||||
@ -0,0 +1,7 @@
|
|||||||
|
/**
|
||||||
|
* subscription-setting router
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { factories } from '@strapi/strapi';
|
||||||
|
|
||||||
|
export default factories.createCoreRouter('api::subscription-setting.subscription-setting');
|
||||||
@ -0,0 +1,7 @@
|
|||||||
|
/**
|
||||||
|
* subscription-setting service
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { factories } from '@strapi/strapi';
|
||||||
|
|
||||||
|
export default factories.createCoreService('api::subscription-setting.subscription-setting');
|
||||||
47
src/api/subscription/content-types/subscription/schema.json
Normal file
47
src/api/subscription/content-types/subscription/schema.json
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
{
|
||||||
|
"kind": "collectionType",
|
||||||
|
"collectionName": "subscriptions",
|
||||||
|
"info": {
|
||||||
|
"singularName": "subscription",
|
||||||
|
"pluralName": "subscriptions",
|
||||||
|
"displayName": "Subscription"
|
||||||
|
},
|
||||||
|
"options": {
|
||||||
|
"draftAndPublish": true
|
||||||
|
},
|
||||||
|
"pluginOptions": {},
|
||||||
|
"attributes": {
|
||||||
|
"customer": {
|
||||||
|
"type": "relation",
|
||||||
|
"relation": "manyToOne",
|
||||||
|
"target": "api::customer.customer",
|
||||||
|
"inversedBy": "subscriptions"
|
||||||
|
},
|
||||||
|
"active": {
|
||||||
|
"type": "boolean",
|
||||||
|
"required": true,
|
||||||
|
"default": false
|
||||||
|
},
|
||||||
|
"expiresAt": {
|
||||||
|
"type": "datetime",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
"subscription_history": {
|
||||||
|
"type": "relation",
|
||||||
|
"relation": "oneToOne",
|
||||||
|
"target": "api::subscription-history.subscription-history",
|
||||||
|
"inversedBy": "subscription"
|
||||||
|
},
|
||||||
|
"subscription_rewards": {
|
||||||
|
"type": "relation",
|
||||||
|
"relation": "oneToMany",
|
||||||
|
"target": "api::subscription-reward.subscription-reward",
|
||||||
|
"mappedBy": "subscription"
|
||||||
|
},
|
||||||
|
"nextSubscription": {
|
||||||
|
"type": "relation",
|
||||||
|
"relation": "oneToOne",
|
||||||
|
"target": "api::subscription.subscription"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
7
src/api/subscription/controllers/subscription.ts
Normal file
7
src/api/subscription/controllers/subscription.ts
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
/**
|
||||||
|
* subscription controller
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { factories } from '@strapi/strapi'
|
||||||
|
|
||||||
|
export default factories.createCoreController('api::subscription.subscription');
|
||||||
7
src/api/subscription/routes/subscription.ts
Normal file
7
src/api/subscription/routes/subscription.ts
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
/**
|
||||||
|
* subscription router
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { factories } from '@strapi/strapi';
|
||||||
|
|
||||||
|
export default factories.createCoreRouter('api::subscription.subscription');
|
||||||
7
src/api/subscription/services/subscription.ts
Normal file
7
src/api/subscription/services/subscription.ts
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
/**
|
||||||
|
* subscription service
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { factories } from '@strapi/strapi';
|
||||||
|
|
||||||
|
export default factories.createCoreService('api::subscription.subscription');
|
||||||
1
src/constants/index.ts
Normal file
1
src/constants/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export const DEFAULT_TZ = 'Europe/Moscow';
|
||||||
13
src/utils/datetime.ts
Normal file
13
src/utils/datetime.ts
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
import dayjs, { type ConfigType } from 'dayjs';
|
||||||
|
import timezone from 'dayjs/plugin/timezone';
|
||||||
|
import utc from 'dayjs/plugin/utc';
|
||||||
|
import 'dayjs/locale/ru';
|
||||||
|
|
||||||
|
if (!dayjs.prototype.tz) {
|
||||||
|
dayjs.extend(utc);
|
||||||
|
dayjs.extend(timezone);
|
||||||
|
}
|
||||||
|
|
||||||
|
dayjs.locale('ru');
|
||||||
|
|
||||||
|
export { dayjs };
|
||||||
@ -9,5 +9,8 @@ export function extractId(input) {
|
|||||||
if (input?.set?.[0]?.id) {
|
if (input?.set?.[0]?.id) {
|
||||||
return input.set[0].id;
|
return input.set[0].id;
|
||||||
}
|
}
|
||||||
|
if (input?.connect?.[0]?.id) {
|
||||||
|
return input.connect[0].id;
|
||||||
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
3
src/utils/index.ts
Normal file
3
src/utils/index.ts
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
export * from './telegram';
|
||||||
|
export * from './db';
|
||||||
|
export * from './datetime';
|
||||||
5
src/utils/telegram.ts
Normal file
5
src/utils/telegram.ts
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
import { Telegraf } from 'telegraf';
|
||||||
|
|
||||||
|
const botToken = strapi.config.get('server.botToken') as string;
|
||||||
|
|
||||||
|
export const bot = new Telegraf(botToken);
|
||||||
376
types/generated/contentTypes.d.ts
vendored
376
types/generated/contentTypes.d.ts
vendored
@ -373,43 +373,6 @@ export interface AdminUser extends Struct.CollectionTypeSchema {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ApiBlockBlock extends Struct.CollectionTypeSchema {
|
|
||||||
collectionName: 'blocks';
|
|
||||||
info: {
|
|
||||||
description: '';
|
|
||||||
displayName: 'Block';
|
|
||||||
pluralName: 'blocks';
|
|
||||||
singularName: 'block';
|
|
||||||
};
|
|
||||||
options: {
|
|
||||||
draftAndPublish: true;
|
|
||||||
};
|
|
||||||
attributes: {
|
|
||||||
client: Schema.Attribute.Relation<'manyToOne', 'api::customer.customer'>;
|
|
||||||
createdAt: Schema.Attribute.DateTime;
|
|
||||||
createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> &
|
|
||||||
Schema.Attribute.Private;
|
|
||||||
datetime_end: Schema.Attribute.DateTime & Schema.Attribute.Required;
|
|
||||||
datetime_start: Schema.Attribute.DateTime & Schema.Attribute.Required;
|
|
||||||
locale: Schema.Attribute.String & Schema.Attribute.Private;
|
|
||||||
localizations: Schema.Attribute.Relation<'oneToMany', 'api::block.block'> &
|
|
||||||
Schema.Attribute.Private;
|
|
||||||
master: Schema.Attribute.Relation<'manyToOne', 'api::customer.customer'>;
|
|
||||||
orders: Schema.Attribute.Relation<'oneToMany', 'api::order.order'>;
|
|
||||||
publishedAt: Schema.Attribute.DateTime;
|
|
||||||
sessions_completed: Schema.Attribute.Integer &
|
|
||||||
Schema.Attribute.DefaultTo<0>;
|
|
||||||
sessions_total: Schema.Attribute.Integer &
|
|
||||||
Schema.Attribute.Required &
|
|
||||||
Schema.Attribute.DefaultTo<10>;
|
|
||||||
state: Schema.Attribute.Enumeration<['created', 'paid', 'deleted']> &
|
|
||||||
Schema.Attribute.DefaultTo<'created'>;
|
|
||||||
updatedAt: Schema.Attribute.DateTime;
|
|
||||||
updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> &
|
|
||||||
Schema.Attribute.Private;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ApiCustomerCustomer extends Struct.CollectionTypeSchema {
|
export interface ApiCustomerCustomer extends Struct.CollectionTypeSchema {
|
||||||
collectionName: 'customers';
|
collectionName: 'customers';
|
||||||
info: {
|
info: {
|
||||||
@ -423,29 +386,55 @@ export interface ApiCustomerCustomer extends Struct.CollectionTypeSchema {
|
|||||||
};
|
};
|
||||||
attributes: {
|
attributes: {
|
||||||
active: Schema.Attribute.Boolean & Schema.Attribute.DefaultTo<false>;
|
active: Schema.Attribute.Boolean & Schema.Attribute.DefaultTo<false>;
|
||||||
blocks: Schema.Attribute.Relation<'oneToMany', 'api::block.block'>;
|
bannedUntil: Schema.Attribute.DateTime;
|
||||||
clients: Schema.Attribute.Relation<'manyToMany', 'api::customer.customer'>;
|
|
||||||
createdAt: Schema.Attribute.DateTime;
|
createdAt: Schema.Attribute.DateTime;
|
||||||
createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> &
|
createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> &
|
||||||
Schema.Attribute.Private;
|
Schema.Attribute.Private;
|
||||||
|
customer_setting: Schema.Attribute.Relation<
|
||||||
|
'oneToOne',
|
||||||
|
'api::customer.customer-setting'
|
||||||
|
>;
|
||||||
|
invited: Schema.Attribute.Relation<'manyToMany', 'api::customer.customer'>;
|
||||||
|
invitedBy: Schema.Attribute.Relation<
|
||||||
|
'manyToMany',
|
||||||
|
'api::customer.customer'
|
||||||
|
>;
|
||||||
locale: Schema.Attribute.String & Schema.Attribute.Private;
|
locale: Schema.Attribute.String & Schema.Attribute.Private;
|
||||||
localizations: Schema.Attribute.Relation<
|
localizations: Schema.Attribute.Relation<
|
||||||
'oneToMany',
|
'oneToMany',
|
||||||
'api::customer.customer'
|
'api::customer.customer'
|
||||||
> &
|
> &
|
||||||
Schema.Attribute.Private;
|
Schema.Attribute.Private;
|
||||||
masters: Schema.Attribute.Relation<'manyToMany', 'api::customer.customer'>;
|
name: Schema.Attribute.String &
|
||||||
name: Schema.Attribute.String & Schema.Attribute.Required;
|
Schema.Attribute.Required &
|
||||||
|
Schema.Attribute.SetMinMaxLength<{
|
||||||
|
maxLength: 100;
|
||||||
|
}>;
|
||||||
orders: Schema.Attribute.Relation<'oneToMany', 'api::order.order'>;
|
orders: Schema.Attribute.Relation<'oneToMany', 'api::order.order'>;
|
||||||
phone: Schema.Attribute.String &
|
phone: Schema.Attribute.String &
|
||||||
Schema.Attribute.Required &
|
Schema.Attribute.Required &
|
||||||
Schema.Attribute.Unique;
|
Schema.Attribute.Unique &
|
||||||
|
Schema.Attribute.SetMinMaxLength<{
|
||||||
|
maxLength: 20;
|
||||||
|
}>;
|
||||||
photoUrl: Schema.Attribute.String;
|
photoUrl: Schema.Attribute.String;
|
||||||
publishedAt: Schema.Attribute.DateTime;
|
publishedAt: Schema.Attribute.DateTime;
|
||||||
role: Schema.Attribute.Enumeration<['client', 'master']> &
|
role: Schema.Attribute.Enumeration<['client', 'master']> &
|
||||||
Schema.Attribute.Required;
|
Schema.Attribute.Required;
|
||||||
services: Schema.Attribute.Relation<'oneToMany', 'api::service.service'>;
|
services: Schema.Attribute.Relation<'oneToMany', 'api::service.service'>;
|
||||||
slots: Schema.Attribute.Relation<'oneToMany', 'api::slot.slot'>;
|
slots: Schema.Attribute.Relation<'oneToMany', 'api::slot.slot'>;
|
||||||
|
subscription_rewards: Schema.Attribute.Relation<
|
||||||
|
'oneToMany',
|
||||||
|
'api::subscription-reward.subscription-reward'
|
||||||
|
>;
|
||||||
|
subscriptions: Schema.Attribute.Relation<
|
||||||
|
'oneToMany',
|
||||||
|
'api::subscription.subscription'
|
||||||
|
>;
|
||||||
|
surname: Schema.Attribute.String &
|
||||||
|
Schema.Attribute.SetMinMaxLength<{
|
||||||
|
maxLength: 100;
|
||||||
|
}>;
|
||||||
telegramId: Schema.Attribute.BigInteger & Schema.Attribute.Unique;
|
telegramId: Schema.Attribute.BigInteger & Schema.Attribute.Unique;
|
||||||
updatedAt: Schema.Attribute.DateTime;
|
updatedAt: Schema.Attribute.DateTime;
|
||||||
updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> &
|
updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> &
|
||||||
@ -453,6 +442,36 @@ export interface ApiCustomerCustomer extends Struct.CollectionTypeSchema {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface ApiCustomerCustomerSetting
|
||||||
|
extends Struct.CollectionTypeSchema {
|
||||||
|
collectionName: 'customer_settings';
|
||||||
|
info: {
|
||||||
|
displayName: 'CustomerSettings';
|
||||||
|
pluralName: 'customer-settings';
|
||||||
|
singularName: 'customer-setting';
|
||||||
|
};
|
||||||
|
options: {
|
||||||
|
draftAndPublish: false;
|
||||||
|
};
|
||||||
|
attributes: {
|
||||||
|
autoRenewSubscription: Schema.Attribute.Boolean;
|
||||||
|
createdAt: Schema.Attribute.DateTime;
|
||||||
|
createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> &
|
||||||
|
Schema.Attribute.Private;
|
||||||
|
customer: Schema.Attribute.Relation<'oneToOne', 'api::customer.customer'>;
|
||||||
|
locale: Schema.Attribute.String & Schema.Attribute.Private;
|
||||||
|
localizations: Schema.Attribute.Relation<
|
||||||
|
'oneToMany',
|
||||||
|
'api::customer.customer-setting'
|
||||||
|
> &
|
||||||
|
Schema.Attribute.Private;
|
||||||
|
publishedAt: Schema.Attribute.DateTime;
|
||||||
|
updatedAt: Schema.Attribute.DateTime;
|
||||||
|
updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> &
|
||||||
|
Schema.Attribute.Private;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
export interface ApiOrderOrder extends Struct.CollectionTypeSchema {
|
export interface ApiOrderOrder extends Struct.CollectionTypeSchema {
|
||||||
collectionName: 'orders';
|
collectionName: 'orders';
|
||||||
info: {
|
info: {
|
||||||
@ -465,18 +484,17 @@ export interface ApiOrderOrder extends Struct.CollectionTypeSchema {
|
|||||||
draftAndPublish: true;
|
draftAndPublish: true;
|
||||||
};
|
};
|
||||||
attributes: {
|
attributes: {
|
||||||
block: Schema.Attribute.Relation<'manyToOne', 'api::block.block'>;
|
|
||||||
client: Schema.Attribute.Relation<'manyToOne', 'api::customer.customer'>;
|
client: Schema.Attribute.Relation<'manyToOne', 'api::customer.customer'>;
|
||||||
createdAt: Schema.Attribute.DateTime;
|
createdAt: Schema.Attribute.DateTime;
|
||||||
createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> &
|
createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> &
|
||||||
Schema.Attribute.Private;
|
Schema.Attribute.Private;
|
||||||
|
datetime_end: Schema.Attribute.DateTime & Schema.Attribute.Required;
|
||||||
|
datetime_start: Schema.Attribute.DateTime & Schema.Attribute.Required;
|
||||||
locale: Schema.Attribute.String & Schema.Attribute.Private;
|
locale: Schema.Attribute.String & Schema.Attribute.Private;
|
||||||
localizations: Schema.Attribute.Relation<'oneToMany', 'api::order.order'> &
|
localizations: Schema.Attribute.Relation<'oneToMany', 'api::order.order'> &
|
||||||
Schema.Attribute.Private;
|
Schema.Attribute.Private;
|
||||||
order_number: Schema.Attribute.Integer;
|
order_number: Schema.Attribute.Integer;
|
||||||
price: Schema.Attribute.Integer;
|
|
||||||
publishedAt: Schema.Attribute.DateTime;
|
publishedAt: Schema.Attribute.DateTime;
|
||||||
service_description: Schema.Attribute.Text;
|
|
||||||
services: Schema.Attribute.Relation<'manyToMany', 'api::service.service'>;
|
services: Schema.Attribute.Relation<'manyToMany', 'api::service.service'>;
|
||||||
slot: Schema.Attribute.Relation<'manyToOne', 'api::slot.slot'>;
|
slot: Schema.Attribute.Relation<'manyToOne', 'api::slot.slot'>;
|
||||||
state: Schema.Attribute.Enumeration<
|
state: Schema.Attribute.Enumeration<
|
||||||
@ -490,8 +508,6 @@ export interface ApiOrderOrder extends Struct.CollectionTypeSchema {
|
|||||||
]
|
]
|
||||||
> &
|
> &
|
||||||
Schema.Attribute.DefaultTo<'created'>;
|
Schema.Attribute.DefaultTo<'created'>;
|
||||||
time_end: Schema.Attribute.Time;
|
|
||||||
time_start: Schema.Attribute.Time;
|
|
||||||
updatedAt: Schema.Attribute.DateTime;
|
updatedAt: Schema.Attribute.DateTime;
|
||||||
updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> &
|
updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> &
|
||||||
Schema.Attribute.Private;
|
Schema.Attribute.Private;
|
||||||
@ -502,7 +518,7 @@ export interface ApiServiceService extends Struct.CollectionTypeSchema {
|
|||||||
collectionName: 'services';
|
collectionName: 'services';
|
||||||
info: {
|
info: {
|
||||||
description: '';
|
description: '';
|
||||||
displayName: 'service';
|
displayName: 'Service';
|
||||||
pluralName: 'services';
|
pluralName: 'services';
|
||||||
singularName: 'service';
|
singularName: 'service';
|
||||||
};
|
};
|
||||||
@ -510,9 +526,11 @@ export interface ApiServiceService extends Struct.CollectionTypeSchema {
|
|||||||
draftAndPublish: true;
|
draftAndPublish: true;
|
||||||
};
|
};
|
||||||
attributes: {
|
attributes: {
|
||||||
|
active: Schema.Attribute.Boolean & Schema.Attribute.DefaultTo<false>;
|
||||||
createdAt: Schema.Attribute.DateTime;
|
createdAt: Schema.Attribute.DateTime;
|
||||||
createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> &
|
createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> &
|
||||||
Schema.Attribute.Private;
|
Schema.Attribute.Private;
|
||||||
|
description: Schema.Attribute.Text;
|
||||||
duration: Schema.Attribute.Time &
|
duration: Schema.Attribute.Time &
|
||||||
Schema.Attribute.Required &
|
Schema.Attribute.Required &
|
||||||
Schema.Attribute.DefaultTo<'01:00:00.000'>;
|
Schema.Attribute.DefaultTo<'01:00:00.000'>;
|
||||||
@ -523,8 +541,19 @@ export interface ApiServiceService extends Struct.CollectionTypeSchema {
|
|||||||
> &
|
> &
|
||||||
Schema.Attribute.Private;
|
Schema.Attribute.Private;
|
||||||
master: Schema.Attribute.Relation<'manyToOne', 'api::customer.customer'>;
|
master: Schema.Attribute.Relation<'manyToOne', 'api::customer.customer'>;
|
||||||
name: Schema.Attribute.String;
|
name: Schema.Attribute.String &
|
||||||
|
Schema.Attribute.Required &
|
||||||
|
Schema.Attribute.SetMinMaxLength<{
|
||||||
|
maxLength: 100;
|
||||||
|
}>;
|
||||||
orders: Schema.Attribute.Relation<'manyToMany', 'api::order.order'>;
|
orders: Schema.Attribute.Relation<'manyToMany', 'api::order.order'>;
|
||||||
|
price: Schema.Attribute.Decimal &
|
||||||
|
Schema.Attribute.SetMinMax<
|
||||||
|
{
|
||||||
|
min: 1;
|
||||||
|
},
|
||||||
|
number
|
||||||
|
>;
|
||||||
publishedAt: Schema.Attribute.DateTime;
|
publishedAt: Schema.Attribute.DateTime;
|
||||||
updatedAt: Schema.Attribute.DateTime;
|
updatedAt: Schema.Attribute.DateTime;
|
||||||
updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> &
|
updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> &
|
||||||
@ -532,36 +561,6 @@ export interface ApiServiceService extends Struct.CollectionTypeSchema {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ApiSettingSetting extends Struct.CollectionTypeSchema {
|
|
||||||
collectionName: 'settings';
|
|
||||||
info: {
|
|
||||||
description: '';
|
|
||||||
displayName: 'Setting';
|
|
||||||
pluralName: 'settings';
|
|
||||||
singularName: 'setting';
|
|
||||||
};
|
|
||||||
options: {
|
|
||||||
draftAndPublish: true;
|
|
||||||
};
|
|
||||||
attributes: {
|
|
||||||
createdAt: Schema.Attribute.DateTime;
|
|
||||||
createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> &
|
|
||||||
Schema.Attribute.Private;
|
|
||||||
locale: Schema.Attribute.String & Schema.Attribute.Private;
|
|
||||||
localizations: Schema.Attribute.Relation<
|
|
||||||
'oneToMany',
|
|
||||||
'api::setting.setting'
|
|
||||||
> &
|
|
||||||
Schema.Attribute.Private;
|
|
||||||
publishedAt: Schema.Attribute.DateTime;
|
|
||||||
recording_by_blocks: Schema.Attribute.Boolean &
|
|
||||||
Schema.Attribute.DefaultTo<false>;
|
|
||||||
updatedAt: Schema.Attribute.DateTime;
|
|
||||||
updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> &
|
|
||||||
Schema.Attribute.Private;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ApiSlotSlot extends Struct.CollectionTypeSchema {
|
export interface ApiSlotSlot extends Struct.CollectionTypeSchema {
|
||||||
collectionName: 'slots';
|
collectionName: 'slots';
|
||||||
info: {
|
info: {
|
||||||
@ -577,7 +576,8 @@ export interface ApiSlotSlot extends Struct.CollectionTypeSchema {
|
|||||||
createdAt: Schema.Attribute.DateTime;
|
createdAt: Schema.Attribute.DateTime;
|
||||||
createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> &
|
createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> &
|
||||||
Schema.Attribute.Private;
|
Schema.Attribute.Private;
|
||||||
date: Schema.Attribute.Date;
|
datetime_end: Schema.Attribute.DateTime & Schema.Attribute.Required;
|
||||||
|
datetime_start: Schema.Attribute.DateTime & Schema.Attribute.Required;
|
||||||
locale: Schema.Attribute.String & Schema.Attribute.Private;
|
locale: Schema.Attribute.String & Schema.Attribute.Private;
|
||||||
localizations: Schema.Attribute.Relation<'oneToMany', 'api::slot.slot'> &
|
localizations: Schema.Attribute.Relation<'oneToMany', 'api::slot.slot'> &
|
||||||
Schema.Attribute.Private;
|
Schema.Attribute.Private;
|
||||||
@ -585,8 +585,212 @@ export interface ApiSlotSlot extends Struct.CollectionTypeSchema {
|
|||||||
orders: Schema.Attribute.Relation<'oneToMany', 'api::order.order'>;
|
orders: Schema.Attribute.Relation<'oneToMany', 'api::order.order'>;
|
||||||
publishedAt: Schema.Attribute.DateTime;
|
publishedAt: Schema.Attribute.DateTime;
|
||||||
state: Schema.Attribute.Enumeration<['open', 'reserved', 'closed']>;
|
state: Schema.Attribute.Enumeration<['open', 'reserved', 'closed']>;
|
||||||
time_end: Schema.Attribute.Time & Schema.Attribute.Required;
|
updatedAt: Schema.Attribute.DateTime;
|
||||||
time_start: Schema.Attribute.Time & Schema.Attribute.Required;
|
updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> &
|
||||||
|
Schema.Attribute.Private;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
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.String &
|
||||||
|
Schema.Attribute.SetMinMaxLength<{
|
||||||
|
maxLength: 20;
|
||||||
|
}>;
|
||||||
|
publishedAt: Schema.Attribute.DateTime;
|
||||||
|
source: Schema.Attribute.Enumeration<
|
||||||
|
['payment', 'trial', 'reward', 'admin', 'renewal']
|
||||||
|
> &
|
||||||
|
Schema.Attribute.Required &
|
||||||
|
Schema.Attribute.DefaultTo<'payment'>;
|
||||||
|
state: Schema.Attribute.Enumeration<['success', 'failed', 'pending']> &
|
||||||
|
Schema.Attribute.Required;
|
||||||
|
subscription: Schema.Attribute.Relation<
|
||||||
|
'oneToOne',
|
||||||
|
'api::subscription.subscription'
|
||||||
|
>;
|
||||||
|
subscription_price: Schema.Attribute.Relation<
|
||||||
|
'oneToOne',
|
||||||
|
'api::subscription-price.subscription-price'
|
||||||
|
>;
|
||||||
|
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: {
|
||||||
|
active: Schema.Attribute.Boolean & Schema.Attribute.DefaultTo<true>;
|
||||||
|
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'>;
|
||||||
|
days: Schema.Attribute.Integer & Schema.Attribute.Required;
|
||||||
|
description: Schema.Attribute.Text;
|
||||||
|
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', 'day', 'week', 'month', 'half_year', 'year']
|
||||||
|
> &
|
||||||
|
Schema.Attribute.Required;
|
||||||
|
publishedAt: Schema.Attribute.DateTime;
|
||||||
|
updatedAt: Schema.Attribute.DateTime;
|
||||||
|
updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> &
|
||||||
|
Schema.Attribute.Private;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ApiSubscriptionRewardSubscriptionReward
|
||||||
|
extends Struct.CollectionTypeSchema {
|
||||||
|
collectionName: 'subscription_rewards';
|
||||||
|
info: {
|
||||||
|
displayName: 'SubscriptionReward';
|
||||||
|
pluralName: 'subscription-rewards';
|
||||||
|
singularName: 'subscription-reward';
|
||||||
|
};
|
||||||
|
options: {
|
||||||
|
draftAndPublish: true;
|
||||||
|
};
|
||||||
|
attributes: {
|
||||||
|
activated: Schema.Attribute.Boolean & Schema.Attribute.DefaultTo<false>;
|
||||||
|
createdAt: Schema.Attribute.DateTime;
|
||||||
|
createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> &
|
||||||
|
Schema.Attribute.Private;
|
||||||
|
days: Schema.Attribute.Integer & Schema.Attribute.Required;
|
||||||
|
description: Schema.Attribute.Text;
|
||||||
|
expiresAt: Schema.Attribute.DateTime & Schema.Attribute.Required;
|
||||||
|
invited: Schema.Attribute.Relation<'oneToOne', 'api::customer.customer'>;
|
||||||
|
locale: Schema.Attribute.String & Schema.Attribute.Private;
|
||||||
|
localizations: Schema.Attribute.Relation<
|
||||||
|
'oneToMany',
|
||||||
|
'api::subscription-reward.subscription-reward'
|
||||||
|
> &
|
||||||
|
Schema.Attribute.Private;
|
||||||
|
owner: Schema.Attribute.Relation<'manyToOne', 'api::customer.customer'>;
|
||||||
|
publishedAt: Schema.Attribute.DateTime;
|
||||||
|
subscription: Schema.Attribute.Relation<
|
||||||
|
'manyToOne',
|
||||||
|
'api::subscription.subscription'
|
||||||
|
>;
|
||||||
|
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;
|
||||||
|
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<20>;
|
||||||
|
proEnabled: Schema.Attribute.Boolean & Schema.Attribute.DefaultTo<false>;
|
||||||
|
publishedAt: Schema.Attribute.DateTime;
|
||||||
|
referralRewardDays: Schema.Attribute.Integer &
|
||||||
|
Schema.Attribute.Required &
|
||||||
|
Schema.Attribute.DefaultTo<1>;
|
||||||
|
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: {
|
||||||
|
active: 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<'manyToOne', 'api::customer.customer'>;
|
||||||
|
expiresAt: Schema.Attribute.DateTime & Schema.Attribute.Required;
|
||||||
|
locale: Schema.Attribute.String & Schema.Attribute.Private;
|
||||||
|
localizations: Schema.Attribute.Relation<
|
||||||
|
'oneToMany',
|
||||||
|
'api::subscription.subscription'
|
||||||
|
> &
|
||||||
|
Schema.Attribute.Private;
|
||||||
|
nextSubscription: Schema.Attribute.Relation<
|
||||||
|
'oneToOne',
|
||||||
|
'api::subscription.subscription'
|
||||||
|
>;
|
||||||
|
publishedAt: Schema.Attribute.DateTime;
|
||||||
|
subscription_history: Schema.Attribute.Relation<
|
||||||
|
'oneToOne',
|
||||||
|
'api::subscription-history.subscription-history'
|
||||||
|
>;
|
||||||
|
subscription_rewards: Schema.Attribute.Relation<
|
||||||
|
'oneToMany',
|
||||||
|
'api::subscription-reward.subscription-reward'
|
||||||
|
>;
|
||||||
updatedAt: Schema.Attribute.DateTime;
|
updatedAt: Schema.Attribute.DateTime;
|
||||||
updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> &
|
updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> &
|
||||||
Schema.Attribute.Private;
|
Schema.Attribute.Private;
|
||||||
@ -1102,12 +1306,16 @@ declare module '@strapi/strapi' {
|
|||||||
'admin::transfer-token': AdminTransferToken;
|
'admin::transfer-token': AdminTransferToken;
|
||||||
'admin::transfer-token-permission': AdminTransferTokenPermission;
|
'admin::transfer-token-permission': AdminTransferTokenPermission;
|
||||||
'admin::user': AdminUser;
|
'admin::user': AdminUser;
|
||||||
'api::block.block': ApiBlockBlock;
|
|
||||||
'api::customer.customer': ApiCustomerCustomer;
|
'api::customer.customer': ApiCustomerCustomer;
|
||||||
|
'api::customer.customer-setting': ApiCustomerCustomerSetting;
|
||||||
'api::order.order': ApiOrderOrder;
|
'api::order.order': ApiOrderOrder;
|
||||||
'api::service.service': ApiServiceService;
|
'api::service.service': ApiServiceService;
|
||||||
'api::setting.setting': ApiSettingSetting;
|
|
||||||
'api::slot.slot': ApiSlotSlot;
|
'api::slot.slot': ApiSlotSlot;
|
||||||
|
'api::subscription-history.subscription-history': ApiSubscriptionHistorySubscriptionHistory;
|
||||||
|
'api::subscription-price.subscription-price': ApiSubscriptionPriceSubscriptionPrice;
|
||||||
|
'api::subscription-reward.subscription-reward': ApiSubscriptionRewardSubscriptionReward;
|
||||||
|
'api::subscription-setting.subscription-setting': ApiSubscriptionSettingSubscriptionSetting;
|
||||||
|
'api::subscription.subscription': ApiSubscriptionSubscription;
|
||||||
'plugin::content-releases.release': PluginContentReleasesRelease;
|
'plugin::content-releases.release': PluginContentReleasesRelease;
|
||||||
'plugin::content-releases.release-action': PluginContentReleasesReleaseAction;
|
'plugin::content-releases.release-action': PluginContentReleasesReleaseAction;
|
||||||
'plugin::i18n.locale': PluginI18NLocale;
|
'plugin::i18n.locale': PluginI18NLocale;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user