From 11596ee01b4e411b8d90407a1e382cc7fa81e385 Mon Sep 17 00:00:00 2001 From: sova-bootstrap Date: Wed, 27 May 2026 19:36:33 +0300 Subject: [PATCH] chore: initial import for test contour --- apps/adminpanel/Chart.yaml | 6 + apps/adminpanel/templates/all.yaml | 77 +++ apps/adminpanel/values-stage.yaml | 8 + apps/adminpanel/values-test.yaml | 8 + apps/adminpanel/values.yaml | 24 + apps/backend/Chart.yaml | 6 + apps/backend/jwt/private.pem | 52 ++ apps/backend/jwt/public.pem | 14 + apps/backend/templates/all.yaml | 232 ++++++++ apps/backend/values-stage.yaml | 10 + apps/backend/values-test.yaml | 9 + apps/backend/values.yaml | 79 +++ argocd/app-of-apps.yaml | 18 + argocd/apps/test-contour.yaml | 94 ++++ argocd/projects/sova-project.yaml | 19 + data/db-init/Chart.yaml | 5 + data/db-init/sql | 1 + data/db-init/templates/db-init-jobs.yaml | 133 +++++ data/db-init/values.yaml | 12 + .../init/01-bitrix-schema-and-seed.sql | 67 +++ data/mysql-simple/mysql.yaml | 48 ++ data/postgres/init/01-create-databases.sql | 1 + .../init/02-backend-schema-and-seed.sql | 509 ++++++++++++++++++ .../init/03-cabinet-schema-and-seed.sql | 296 ++++++++++ data/test/Chart.yaml | 19 + .../mysql-bitrix/schema/01-bitrix-schema.sql | 44 ++ .../sql/mysql-bitrix/seed/01-bitrix-seed.sql | 23 + .../postgres/schema/01-create-databases.sql | 2 + .../sql/postgres/schema/02-backend-schema.sql | 412 ++++++++++++++ .../sql/postgres/schema/03-cabinet-schema.sql | 220 ++++++++ .../seed/01-create-databases.seed.sql | 0 .../sql/postgres/seed/02-backend-seed.sql | 99 ++++ .../sql/postgres/seed/03-cabinet-seed.sql | 78 +++ data/test/templates/db-init-jobs.yaml | 132 +++++ data/test/templates/namespace.yaml | 4 + data/test/values.yaml | 55 ++ 36 files changed, 2816 insertions(+) create mode 100644 apps/adminpanel/Chart.yaml create mode 100644 apps/adminpanel/templates/all.yaml create mode 100644 apps/adminpanel/values-stage.yaml create mode 100644 apps/adminpanel/values-test.yaml create mode 100644 apps/adminpanel/values.yaml create mode 100644 apps/backend/Chart.yaml create mode 100644 apps/backend/jwt/private.pem create mode 100644 apps/backend/jwt/public.pem create mode 100644 apps/backend/templates/all.yaml create mode 100644 apps/backend/values-stage.yaml create mode 100644 apps/backend/values-test.yaml create mode 100644 apps/backend/values.yaml create mode 100644 argocd/app-of-apps.yaml create mode 100644 argocd/apps/test-contour.yaml create mode 100644 argocd/projects/sova-project.yaml create mode 100644 data/db-init/Chart.yaml create mode 120000 data/db-init/sql create mode 100644 data/db-init/templates/db-init-jobs.yaml create mode 100644 data/db-init/values.yaml create mode 100644 data/mysql-bitrix/init/01-bitrix-schema-and-seed.sql create mode 100644 data/mysql-simple/mysql.yaml create mode 100644 data/postgres/init/01-create-databases.sql create mode 100644 data/postgres/init/02-backend-schema-and-seed.sql create mode 100644 data/postgres/init/03-cabinet-schema-and-seed.sql create mode 100644 data/test/Chart.yaml create mode 100644 data/test/sql/mysql-bitrix/schema/01-bitrix-schema.sql create mode 100644 data/test/sql/mysql-bitrix/seed/01-bitrix-seed.sql create mode 100644 data/test/sql/postgres/schema/01-create-databases.sql create mode 100644 data/test/sql/postgres/schema/02-backend-schema.sql create mode 100644 data/test/sql/postgres/schema/03-cabinet-schema.sql create mode 100644 data/test/sql/postgres/seed/01-create-databases.seed.sql create mode 100644 data/test/sql/postgres/seed/02-backend-seed.sql create mode 100644 data/test/sql/postgres/seed/03-cabinet-seed.sql create mode 100644 data/test/templates/db-init-jobs.yaml create mode 100644 data/test/templates/namespace.yaml create mode 100644 data/test/values.yaml diff --git a/apps/adminpanel/Chart.yaml b/apps/adminpanel/Chart.yaml new file mode 100644 index 0000000..0ecb559 --- /dev/null +++ b/apps/adminpanel/Chart.yaml @@ -0,0 +1,6 @@ +apiVersion: v2 +name: adminpanel +description: Sova admin panel SPA +type: application +version: 0.1.0 +appVersion: "1.0.0" diff --git a/apps/adminpanel/templates/all.yaml b/apps/adminpanel/templates/all.yaml new file mode 100644 index 0000000..97fc556 --- /dev/null +++ b/apps/adminpanel/templates/all.yaml @@ -0,0 +1,77 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: adminpanel-env-js + namespace: {{ .Values.namespace }} +data: + env.js: | + window.__ENV__ = { + API_BASE_URL: {{ .Values.runtimeEnv.API_BASE_URL | quote }} + }; +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: adminpanel + namespace: {{ .Values.namespace }} + labels: + app: adminpanel +spec: + replicas: {{ .Values.replicaCount }} + selector: + matchLabels: + app: adminpanel + template: + metadata: + labels: + app: adminpanel + spec: + containers: + - name: adminpanel + image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + ports: + - containerPort: 80 + volumeMounts: + - name: env-js + mountPath: /config/env.js + subPath: env.js + resources: + {{- toYaml .Values.resources | nindent 12 }} + volumes: + - name: env-js + configMap: + name: adminpanel-env-js +--- +apiVersion: v1 +kind: Service +metadata: + name: adminpanel + namespace: {{ .Values.namespace }} +spec: + selector: + app: adminpanel + ports: + - port: 80 + targetPort: 80 +--- +{{- if .Values.ingress.enabled }} +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: adminpanel + namespace: {{ .Values.namespace }} +spec: + ingressClassName: {{ .Values.ingress.className }} + rules: + - host: {{ .Values.ingress.host }} + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: adminpanel + port: + number: 80 +{{- end }} diff --git a/apps/adminpanel/values-stage.yaml b/apps/adminpanel/values-stage.yaml new file mode 100644 index 0000000..20d678b --- /dev/null +++ b/apps/adminpanel/values-stage.yaml @@ -0,0 +1,8 @@ +ingress: + host: admin.stage.sova.local + +runtimeEnv: + API_BASE_URL: https://api.stage.sova.local + +image: + tag: adminpanel-v0.0.0-stage diff --git a/apps/adminpanel/values-test.yaml b/apps/adminpanel/values-test.yaml new file mode 100644 index 0000000..b474ab4 --- /dev/null +++ b/apps/adminpanel/values-test.yaml @@ -0,0 +1,8 @@ +ingress: + host: admin.test.sova.local + +runtimeEnv: + API_BASE_URL: http://api.test.sova.local + +image: + tag: local-test diff --git a/apps/adminpanel/values.yaml b/apps/adminpanel/values.yaml new file mode 100644 index 0000000..2fbe64f --- /dev/null +++ b/apps/adminpanel/values.yaml @@ -0,0 +1,24 @@ +namespace: sova-test + +image: + repository: sova-adminpanel + tag: local-test + pullPolicy: IfNotPresent + +replicaCount: 1 + +ingress: + enabled: true + className: nginx + host: admin.test.sova.local + +runtimeEnv: + API_BASE_URL: http://api.test.sova.local + +resources: + requests: + cpu: 50m + memory: 64Mi + limits: + cpu: 200m + memory: 128Mi diff --git a/apps/backend/Chart.yaml b/apps/backend/Chart.yaml new file mode 100644 index 0000000..550276b --- /dev/null +++ b/apps/backend/Chart.yaml @@ -0,0 +1,6 @@ +apiVersion: v2 +name: backend +description: Sova Symfony backend +type: application +version: 0.1.0 +appVersion: "1.0.0" diff --git a/apps/backend/jwt/private.pem b/apps/backend/jwt/private.pem new file mode 100644 index 0000000..8f274d7 --- /dev/null +++ b/apps/backend/jwt/private.pem @@ -0,0 +1,52 @@ +-----BEGIN PRIVATE KEY----- +MIIJQQIBADANBgkqhkiG9w0BAQEFAASCCSswggknAgEAAoICAQCkU4Upp//lZHH6 +P6AYzl5lT4p/R3lBVPKnCHyvPH/fq34740YUc8eoOLCT9Sr7+DNuIRJa5YLQUqo1 +BsmOYUI6I97mzAuIQQczuMbC+srXq9ivRbGvvteUuP4ZS/Tu3rd2hUFk4D0ytUdG +emgwOs+CrzOcVtCfgwBohYYHwMmODjdP/VkrGHP2cJtjKcT4HzW/iSfR/YVMa4fD +ujNPB2kOplAYbJZUkQ0wZfHbFYJ7bnn7eln/XEsxKDsWtvtOKbjKITW/FRjIl+W8 +rY9rfb2jtrZoKS7WlDhdz4MvzDz0CEaHQi5SugNH1yoJ27PP27IO1XorCr/Mp05c +kK5d8QJaeGz+0OlLw5MHG6ep5YqbYdY8oTkSNJpfH/5ndp6B+pL2z0640sURKPLv +Rslfs7HcizcRhuCvtirrzoitfLfyC3QciW7yglS21F9bMtoy/M/9ea7HrhjRFI2O +hYX7CU6xAywEVqNtlWQ48gWR8AxgtV60e91FEgNC/YZWJvx2jd3+PEkX7+rqg21N +Z/8B95Y2woOhedcB9jzx+Tcd/O8jKzk3rH6/vbVS8rrQxDRCXFwS5FB5Mz/FfWm6 +Vhife1FC/Umag+5YpM6lkR5i16AlStqfOdGIr2JXox9gYNk2kJmyJWCG/Rwdd8rZ +06Z2XRTEH77j7yeMbmUadu3o5J3zbwIDAQABAoICAAlr5ncgdDoFO8myyy2Q63WY +jWLFyMx3n9/2yxtK9zPuQ7MQUUzL5JcfBPS+ukOvE9fNGp3OieUC0FJw/K5moiLu +OpH2AfVCcTTEc9TrByU9a5OFBe6DHR4gSyVNJxJo/5DSjBDKEIgvP5JpYz7cqFgg +Tm+4xIZYvvW/LhOUuJml9ALojiu7364x/568XtgxBeZg6UEPbYyXn7WXn+h4jsvx +uibkVuwrUtvDBI5gmdYU2/aQqcdL1d3QJi8jt53gI4GnTMsTXRPnLZtXQiFSGMTh +rWyka9SOs/qg8q8TYS1GqjCIGVrR4m1Eh1sAVztkJ73U/IeqOpvzvbjt7KljL5TD +tZFcgV4pVYUDMuz2/4wFY8//9ubx7lweizwmdF+XZ/favmUSwVwLYPA8ouY6Z9SA +ZM9kCupe/evsJzd9xQ0Hkh47HAZJzhMPUscq3knMw524BAFMy4a+mcXIspiVsXmP +Ngmf6yVPk6oinU3nF5Hab1sFqMAvcJVroE/wd/af7bTbA+jSMs8k2pLF89aERy8O +iCvERF6KEEcbzKnTiTKpXTBqHgVVRqHAyu92rMtNh1wUWBOgmTs/YdNbvTCAOQRc +PXekp86EEAF48oACllxIRteAM3RwGYT1uESlD7o31wLuGoXb04pLcoEIawq5554J +QaZWMUyhTKvy9N2P6StdAoIBAQDf+MVPo02src4+GpPOB1Soc6PiHFbytn9Xr4+Y +QaMM0EkSD5r0WGxQlF2GO2spP3olDzuRMyl8lKiY32dy9oAx5qRThFkTt63lHEjP +aqNlqH6TAnFCPydjeeo/mfP+xNkw3eTFuiDalnZAqttYYcLV4vQ73jRqNzfV1Iqu +FU1dii6yHbKwUo/v8ONUGjIkwJcRcGt3+gZ9eFfc8cd8Llsljho3CHAxEXmfP3dJ +EgVXqal4DOdZLTd1BRZ5R0/8O7zjzgdh4GT/7+eMYGsJ8kFzp+RrVHwUgLuFOvJ8 +fy8OhST4ClEl7sNhhwAdlxpStuBsThwKdpSIT2hMEYRLmeQ1AoIBAQC70zpIksOe +qr4dFkF2SAkawTzAadPC+fqh5HHDJKBDiFdemK/Ch5GvL40urZO07BJUn/bgbzDd +JevcgMtWDw8WJQFOu4c4BCjTnLKwddFDu/yx5BSwZrljGa3Y9KBzfUF6phdB09tp +5ouokdRfW8slM12HLI19z3Wpoy0m8t96opWLrzR1rop+qEgc6dsF6yoMw1d/Ylxb +lijN5wC2kw1oo1RIbq761+YJnZoG63aIUFSpzyMGmvZd5EzSUoDlnn6NuZTT8kd0 +DZ0UpwLM8Eq+A/ktVDrLMEvgfcQWrLh45q5qubejpLVHxoahplxZyI03ziWvgZiC +bGi20Dr8O2WTAoIBACQH0j4oiENiRo6JGgQH+9+JkvC6HGa5Yy0JCjG1RXS3QToN +lqD+ZJZl99GzV17wXkb991g5gdAP3juRnQPKkf71GrRw0x+v6eK0tSXhAt5Ex/AA +cZX1sPF42G1Y5/6xTjtlRvtkIQrpL6bhlZ3XRE/CTgYfjhEURwA4TAMLXEHTDAYN +bwSck5lHCFssR6rP7L2adz960nZ22LOrlartji4xeRgnXF0YcZdjz13K718V5TRx +5vnao1RI+D+UcFKkjZOcPmXJgpYF0xsrG60i8tKXTNDTa46k0wXw4LeUgk50rujU +SA+xJG9ZF3SrLUnnL51cx3gLcYOoOqAaJU1AOY0CggEAKwyd5jZlSb+etXH9bQvT +smMp9nwLAjxjeqmufWiupuvgApmCZ1bFSF7gwBseqLAW/3hukEBL9dQUPET01fO7 +pHq00wPeWTNy3BWlSxal8R1sLKW3LDtPMGyZUQm4oN/Lmz3oRLk3KA2kYu2RvI2A +gTVFsY6/m19qe4gf+DZgjG4pUovEvVhU+/S8GoxrG+8rgyNesZ6sxn0jOxZALpiD +0UDmN3fO+UV0vy11OTLMxy+KSCVmxMPNxfVmuioYywhJv1gSyYVVZT8dirdAyBIn +P2gPu5j7pMicC4cn436RBXzx6xpIAeTle97/ypsjvZxe6bSBJLnSZ8pLMeOGMXu3 +qwKCAQBciBLuwfG7zLjMZ+yP02c9tIkBbKlAmDbxZa254Fc0g20z1VCEvoXbZzZN +zobFHqh+/3MV6srOZ9b2mZ1Bsa27JFe1IomjWbaIYxDhowwkSL4sjyz6zeXJ25pc +f3eInXcOO9x/CIt3jEKUk/D9pBt7xCzomL5QxSVZLcotx29mPxk/SOq/a2iSp26o ++Wd3KHlxMA99QFQqIWwbLi/wAmi/z/mEBW5ga/dYhylIZuSAjVOiAjgJKyciIWN2 +bVJ3DHJncIjvfmcG7pgb74dF/qDfyTaoVjGgKARFQQ35RnFbtsmbKrXJodXu0P7D +Qj4/0IvpjRaHVLVf2Nscjx/7Km6N +-----END PRIVATE KEY----- diff --git a/apps/backend/jwt/public.pem b/apps/backend/jwt/public.pem new file mode 100644 index 0000000..d2a4d54 --- /dev/null +++ b/apps/backend/jwt/public.pem @@ -0,0 +1,14 @@ +-----BEGIN PUBLIC KEY----- +MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEApFOFKaf/5WRx+j+gGM5e +ZU+Kf0d5QVTypwh8rzx/36t+O+NGFHPHqDiwk/Uq+/gzbiESWuWC0FKqNQbJjmFC +OiPe5swLiEEHM7jGwvrK16vYr0Wxr77XlLj+GUv07t63doVBZOA9MrVHRnpoMDrP +gq8znFbQn4MAaIWGB8DJjg43T/1ZKxhz9nCbYynE+B81v4kn0f2FTGuHw7ozTwdp +DqZQGGyWVJENMGXx2xWCe255+3pZ/1xLMSg7Frb7Tim4yiE1vxUYyJflvK2Pa329 +o7a2aCku1pQ4Xc+DL8w89AhGh0IuUroDR9cqCduzz9uyDtV6Kwq/zKdOXJCuXfEC +Wnhs/tDpS8OTBxunqeWKm2HWPKE5EjSaXx/+Z3aegfqS9s9OuNLFESjy70bJX7Ox +3Is3EYbgr7Yq686IrXy38gt0HIlu8oJUttRfWzLaMvzP/Xmux64Y0RSNjoWF+wlO +sQMsBFajbZVkOPIFkfAMYLVetHvdRRIDQv2GVib8do3d/jxJF+/q6oNtTWf/AfeW +NsKDoXnXAfY88fk3HfzvIys5N6x+v721UvK60MQ0QlxcEuRQeTM/xX1pulYYn3tR +Qv1JmoPuWKTOpZEeYtegJUranznRiK9iV6MfYGDZNpCZsiVghv0cHXfK2dOmdl0U +xB++4+8njG5lGnbt6OSd828CAwEAAQ== +-----END PUBLIC KEY----- diff --git a/apps/backend/templates/all.yaml b/apps/backend/templates/all.yaml new file mode 100644 index 0000000..f140ba7 --- /dev/null +++ b/apps/backend/templates/all.yaml @@ -0,0 +1,232 @@ +{{- if .Values.jwt.enabled }} +apiVersion: v1 +kind: Secret +metadata: + name: backend-jwt + namespace: {{ .Values.namespace }} +type: Opaque +data: + private.pem: {{ .Files.Get "jwt/private.pem" | b64enc }} + public.pem: {{ .Files.Get "jwt/public.pem" | b64enc }} +--- +{{- end }} +apiVersion: v1 +kind: Secret +metadata: + name: backend-env + namespace: {{ .Values.namespace }} + annotations: + helm.sh/hook: pre-install,pre-upgrade + helm.sh/hook-weight: "-10" + helm.sh/hook-delete-policy: before-hook-creation +type: Opaque +stringData: +{{- range $key, $val := .Values.secrets }} + {{ $key }}: {{ $val | quote }} +{{- end }} +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: backend-nginx-config + namespace: {{ .Values.namespace }} +data: + default.conf: | + server { + listen 8080; + server_name _; + root /app/public; + index index.php; + client_max_body_size 108M; + location / { + try_files $uri /index.php$is_args$args; + } + location ~* \.(?:jpg|jpeg|gif|png|ico|css|js|svg|woff2)$ { + expires 1y; + add_header Cache-Control "public, immutable"; + access_log off; + try_files $uri =404; + } + location ~ ^/index\.php(/|$) { + fastcgi_pass 127.0.0.1:9000; + fastcgi_split_path_info ^(.+\.php)(/.*)$; + include fastcgi_params; + fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name; + fastcgi_param DOCUMENT_ROOT $realpath_root; + fastcgi_param HTTP_PROXY ""; + internal; + } + location ~ \.php$ { + return 404; + } + } +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: backend + namespace: {{ .Values.namespace }} + labels: + app: backend + env: test +spec: + replicas: {{ .Values.replicaCount }} + selector: + matchLabels: + app: backend + template: + metadata: + labels: + app: backend + env: test + spec: + containers: + - name: php-fpm + image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + ports: + - containerPort: 9000 + name: fpm + envFrom: + - secretRef: + name: backend-env + env: + - name: JWT_SECRET_KEY + value: /app/config/jwt/private.pem + - name: JWT_PUBLIC_KEY + value: /app/config/jwt/public.pem +{{- range $key, $val := .Values.env }} + - name: {{ $key }} + value: {{ $val | quote }} +{{- end }} + volumeMounts: + - name: app-public + mountPath: /app/public + - name: jwt-keys + mountPath: /app/config/jwt + readOnly: true + resources: + {{- toYaml .Values.resources.php | nindent 12 }} + - name: nginx + image: {{ .Values.nginx.image }} + ports: + - containerPort: 8080 + name: http + volumeMounts: + - name: app-public + mountPath: /app/public + readOnly: true + - name: nginx-config + mountPath: /etc/nginx/conf.d/default.conf + subPath: default.conf + resources: + {{- toYaml .Values.resources.nginx | nindent 12 }} + initContainers: + - name: copy-public + image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" + command: ["sh", "-c", "cp -a /app/public/. /public/"] + volumeMounts: + - name: app-public + mountPath: /public + volumes: + - name: app-public + emptyDir: {} + - name: nginx-config + configMap: + name: backend-nginx-config + - name: jwt-keys + secret: + secretName: backend-jwt +--- +apiVersion: v1 +kind: Service +metadata: + name: backend + namespace: {{ .Values.namespace }} +spec: + selector: + app: backend + ports: + - name: http + port: 80 + targetPort: 8080 +--- +{{- if .Values.ingress.enabled }} +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: backend + namespace: {{ .Values.namespace }} +spec: + ingressClassName: {{ .Values.ingress.className }} + rules: + - host: {{ .Values.ingress.host }} + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: backend + port: + number: 80 +{{- end }} +--- +{{- if .Values.migrate.enabled }} +apiVersion: batch/v1 +kind: Job +metadata: + name: backend-migrate + namespace: {{ .Values.namespace }} + annotations: + helm.sh/hook: pre-install,pre-upgrade + helm.sh/hook-weight: "0" + helm.sh/hook-delete-policy: before-hook-creation +spec: + template: + spec: + restartPolicy: Never + containers: + - name: migrate + image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" + command: ["php", "bin/console", "doctrine:migrations:migrate", "--no-interaction"] + envFrom: + - secretRef: + name: backend-env + env: +{{- range $key, $val := .Values.env }} + - name: {{ $key }} + value: {{ $val | quote }} +{{- end }} +{{- end }} +--- +{{- if .Values.cronjobs.clearScheduleCache.enabled }} +apiVersion: batch/v1 +kind: CronJob +metadata: + name: backend-clear-schedule-cache + namespace: {{ .Values.namespace }} +spec: + schedule: {{ .Values.cronjobs.clearScheduleCache.schedule | quote }} + concurrencyPolicy: Forbid + successfulJobsHistoryLimit: 3 + failedJobsHistoryLimit: 3 + jobTemplate: + spec: + activeDeadlineSeconds: 3600 + template: + spec: + restartPolicy: OnFailure + containers: + - name: console + image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" + command: {{ .Values.cronjobs.clearScheduleCache.command | toJson }} + envFrom: + - secretRef: + name: backend-env + env: +{{- range $key, $val := .Values.env }} + - name: {{ $key }} + value: {{ $val | quote }} +{{- end }} +{{- end }} diff --git a/apps/backend/values-stage.yaml b/apps/backend/values-stage.yaml new file mode 100644 index 0000000..71a24f0 --- /dev/null +++ b/apps/backend/values-stage.yaml @@ -0,0 +1,10 @@ +ingress: + host: api.stage.sova.local + +image: + tag: backend-v0.0.0-stage + +env: + API_PUBLIC_URL: https://api.stage.sova.local + API_BASE_URL: https://api.stage.sova.local + INTEGRATIONS_STUB_MODE: "true" diff --git a/apps/backend/values-test.yaml b/apps/backend/values-test.yaml new file mode 100644 index 0000000..fd20720 --- /dev/null +++ b/apps/backend/values-test.yaml @@ -0,0 +1,9 @@ +ingress: + host: api.test.sova.local + +image: + tag: local-test + +env: + API_PUBLIC_URL: http://api.test.sova.local + API_BASE_URL: http://api.test.sova.local diff --git a/apps/backend/values.yaml b/apps/backend/values.yaml new file mode 100644 index 0000000..25ed80d --- /dev/null +++ b/apps/backend/values.yaml @@ -0,0 +1,79 @@ +namespace: sova-test + +image: + repository: sova-backend + tag: local-test + pullPolicy: IfNotPresent + +nginx: + image: nginx:1.27-alpine + +replicaCount: 1 + +ingress: + enabled: true + className: nginx + host: api.test.sova.local + tls: false + +resources: + php: + requests: + cpu: 100m + memory: 256Mi + limits: + cpu: 500m + memory: 512Mi + nginx: + requests: + cpu: 50m + memory: 64Mi + limits: + cpu: 200m + memory: 128Mi + +env: + APP_ENV: prod + APP_DEBUG: "0" + MIS_URL: http://mis-mock.sova-mocks.svc.cluster.local:8080 + WIDGET_API_URL: http://mis-mock.sova-mocks.svc.cluster.local:8080 + BITRIX_URL: http://mis-mock.sova-mocks.svc.cluster.local:8080 + SMARTCAPTCHA_URL: http://mis-mock.sova-mocks.svc.cluster.local:8080 + CT_URL: http://mis-mock.sova-mocks.svc.cluster.local:8080 + API_PUBLIC_URL: http://api.test.sova.local + API_BASE_URL: http://api.test.sova.local + INTEGRATIONS_STUB_MODE: "true" + MAILER_DSN: smtp://mailpit.sova-mocks.svc.cluster.local:1025 + MESSENGER_TRANSPORT_DSN: doctrine://default?auto_setup=0 + CORS_ALLOW_ORIGIN: "['http://admin.test.sova.local','https://admin.test.sova.local']" + +secrets: + APP_SECRET: change-me-test-secret + DATABASE_URL: postgresql://sova_test:sova_test_pass@postgresql-test.sova-data-test.svc.cluster.local:5432/sova_backend_test?serverVersion=16&charset=utf8 + DATABASE_CABINET_URL: postgresql://sova_test:sova_test_pass@postgresql-test.sova-data-test.svc.cluster.local:5432/sova_cabinet_test?serverVersion=16&charset=utf8 + DATABASE_BITRIX_URL: mysql://bitrix_test:bitrix_test_pass@mysql-bitrix-test.sova-data-test.svc.cluster.local:3306/sova_bitrix_test?serverVersion=8.0 + REDIS_URL: redis://:redis_test_pass@redis-test-master.sova-data-test.svc.cluster.local:6379/0 + JWT_PASSPHRASE: "" + AES_SECRET_KEY: test-aes-secret-key-32bytes-min!! + MAILER_ACCESS_TOKEN: test-mailer-token + SMSRU_URL: http://noop.invalid + SMSRU_TOKEN: noop + SMSRU_SENDER: noop + SMS4B_URL: http://noop.invalid + SMS4B_TOKEN: noop + SMS4B_SENDER: noop + CT_PARAMS: "91:1:token" + SMARTCAPTCHA_KEY: test-key + API_CLIENT: sova-test-bot + +migrate: + enabled: false + +jwt: + enabled: true + +cronjobs: + clearScheduleCache: + enabled: true + schedule: "0 */6 * * *" + command: ["php", "bin/console", "app:schedule:clear-cache"] diff --git a/argocd/app-of-apps.yaml b/argocd/app-of-apps.yaml new file mode 100644 index 0000000..8ca0186 --- /dev/null +++ b/argocd/app-of-apps.yaml @@ -0,0 +1,18 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: sova-root + namespace: argocd +spec: + project: default + source: + repoURL: http://git.sova.local/sova/sova-deploy.git + targetRevision: main + path: argocd/apps + destination: + server: https://kubernetes.default.svc + namespace: argocd + syncPolicy: + automated: + prune: true + selfHeal: true diff --git a/argocd/apps/test-contour.yaml b/argocd/apps/test-contour.yaml new file mode 100644 index 0000000..20162a0 --- /dev/null +++ b/argocd/apps/test-contour.yaml @@ -0,0 +1,94 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: data-test + namespace: argocd +spec: + project: sova + source: + repoURL: http://git.sova.local/sova/sova-deploy.git + targetRevision: main + path: data/test + helm: + valueFiles: + - values.yaml + destination: + server: https://kubernetes.default.svc + namespace: sova-data-test + syncPolicy: + automated: + prune: true + selfHeal: true + syncOptions: + - CreateNamespace=true +--- +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: mocks-test + namespace: argocd +spec: + project: sova + source: + repoURL: http://git.sova.local/sova/sova-mocks.git + targetRevision: main + path: charts/mocks + destination: + server: https://kubernetes.default.svc + namespace: sova-mocks + syncPolicy: + automated: + prune: true + selfHeal: true + syncOptions: + - CreateNamespace=true +--- +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: backend-test + namespace: argocd +spec: + project: sova + source: + repoURL: http://git.sova.local/sova/sova-deploy.git + targetRevision: main + path: apps/backend + helm: + valueFiles: + - values.yaml + - values-test.yaml + destination: + server: https://kubernetes.default.svc + namespace: sova-test + syncPolicy: + automated: + prune: true + selfHeal: true + syncOptions: + - CreateNamespace=true +--- +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: adminpanel-test + namespace: argocd +spec: + project: sova + source: + repoURL: http://git.sova.local/sova/sova-deploy.git + targetRevision: main + path: apps/adminpanel + helm: + valueFiles: + - values.yaml + - values-test.yaml + destination: + server: https://kubernetes.default.svc + namespace: sova-test + syncPolicy: + automated: + prune: true + selfHeal: true + syncOptions: + - CreateNamespace=true diff --git a/argocd/projects/sova-project.yaml b/argocd/projects/sova-project.yaml new file mode 100644 index 0000000..fd6dda6 --- /dev/null +++ b/argocd/projects/sova-project.yaml @@ -0,0 +1,19 @@ +apiVersion: argoproj.io/v1alpha1 +kind: AppProject +metadata: + name: sova + namespace: argocd +spec: + description: Sova applications + sourceRepos: + - '*' + destinations: + - namespace: sova-test + server: https://kubernetes.default.svc + - namespace: sova-data-test + server: https://kubernetes.default.svc + - namespace: sova-mocks + server: https://kubernetes.default.svc + clusterResourceWhitelist: + - group: '*' + kind: '*' diff --git a/data/db-init/Chart.yaml b/data/db-init/Chart.yaml new file mode 100644 index 0000000..e7baa09 --- /dev/null +++ b/data/db-init/Chart.yaml @@ -0,0 +1,5 @@ +apiVersion: v2 +name: db-init +description: Schema then seed for test databases +type: application +version: 0.1.0 diff --git a/data/db-init/sql b/data/db-init/sql new file mode 120000 index 0000000..0b572b1 --- /dev/null +++ b/data/db-init/sql @@ -0,0 +1 @@ +../test/sql \ No newline at end of file diff --git a/data/db-init/templates/db-init-jobs.yaml b/data/db-init/templates/db-init-jobs.yaml new file mode 100644 index 0000000..30b22b4 --- /dev/null +++ b/data/db-init/templates/db-init-jobs.yaml @@ -0,0 +1,133 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: postgres-schema-sql + namespace: {{ .Values.namespace }} +data: +{{- range $path, $_ := .Files.Glob "sql/postgres/schema/*.sql" }} + {{ base $path }}: | +{{ $.Files.Get $path | indent 4 }} +{{- end }} +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: postgres-seed-sql + namespace: {{ .Values.namespace }} +data: +{{- range $path, $_ := .Files.Glob "sql/postgres/seed/*.sql" }} + {{ base $path }}: | +{{ $.Files.Get $path | indent 4 }} +{{- end }} +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: mysql-schema-sql + namespace: {{ .Values.namespace }} +data: +{{- range $path, $_ := .Files.Glob "sql/mysql-bitrix/schema/*.sql" }} + {{ base $path }}: | +{{ $.Files.Get $path | indent 4 }} +{{- end }} +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: mysql-seed-sql + namespace: {{ .Values.namespace }} +data: +{{- range $path, $_ := .Files.Glob "sql/mysql-bitrix/seed/*.sql" }} + {{ base $path }}: | +{{ $.Files.Get $path | indent 4 }} +{{- end }} +--- +apiVersion: batch/v1 +kind: Job +metadata: + name: db-init + namespace: {{ .Values.namespace }} +spec: + backoffLimit: 2 + ttlSecondsAfterFinished: 3600 + template: + spec: + restartPolicy: OnFailure + initContainers: + - name: wait-pg + image: postgres:16-alpine + command: + - sh + - -c + - | + until pg_isready -h {{ .Values.postgres.host }} -p 5432 -U {{ .Values.postgres.user }}; do sleep 3; done + - name: wait-mysql + image: mysql:8.0 + env: + - name: MYSQL_PWD + value: {{ .Values.mysql.password | quote }} + command: + - sh + - -c + - | + until mysqladmin ping -h {{ .Values.mysql.host }} -u{{ .Values.mysql.user }} --silent; do sleep 3; done + containers: + - name: init + image: postgres:16-alpine + env: + - name: PGPASSWORD + value: {{ .Values.postgres.password | quote }} + - name: MYSQL_PWD + value: {{ .Values.mysql.password | quote }} + command: + - sh + - -c + - | + set -e + echo "=== Phase 1: schema ===" + for f in $(ls /schema/postgres/*.sql 2>/dev/null | sort); do + [ -s "$f" ] || continue + echo "PG schema: $(basename $f)" + psql -h {{ .Values.postgres.host }} -U {{ .Values.postgres.user }} -d postgres -v ON_ERROR_STOP=1 -f "$f" + done + apk add --no-cache mariadb-client >/dev/null + for f in $(ls /schema/mysql/*.sql 2>/dev/null | sort); do + [ -s "$f" ] || continue + echo "MySQL schema: $(basename $f)" + mariadb --skip-ssl -h {{ .Values.mysql.host }} -u{{ .Values.mysql.user }} {{ .Values.mysql.database }} < "$f" + done + echo "=== Phase 2: seed ===" + for f in $(ls /seed/postgres/*.sql 2>/dev/null | sort); do + [ -s "$f" ] || continue + echo "PG seed: $(basename $f)" + psql -h {{ .Values.postgres.host }} -U {{ .Values.postgres.user }} -d postgres -v ON_ERROR_STOP=1 -f "$f" + done + for f in $(ls /seed/mysql/*.sql 2>/dev/null | sort); do + [ -s "$f" ] || continue + echo "MySQL seed: $(basename $f)" + mariadb --skip-ssl -h {{ .Values.mysql.host }} -u{{ .Values.mysql.user }} {{ .Values.mysql.database }} < "$f" + done + echo "DB init complete" + volumeMounts: + - name: pg-schema + mountPath: /schema/postgres + - name: mysql-schema + mountPath: /schema/mysql + - name: pg-seed + mountPath: /seed/postgres + - name: mysql-seed + mountPath: /seed/mysql + volumes: + - name: pg-schema + configMap: + name: postgres-schema-sql + - name: mysql-schema + configMap: + name: mysql-schema-sql + - name: pg-seed + configMap: + name: postgres-seed-sql + - name: mysql-seed + configMap: + name: mysql-seed-sql + diff --git a/data/db-init/values.yaml b/data/db-init/values.yaml new file mode 100644 index 0000000..ffd4784 --- /dev/null +++ b/data/db-init/values.yaml @@ -0,0 +1,12 @@ +namespace: sova-data-test + +postgres: + host: postgresql-test.sova-data-test.svc.cluster.local + user: sova_test + password: sova_test_pass + +mysql: + host: mysql-bitrix-test.sova-data-test.svc.cluster.local + user: bitrix_test + password: bitrix_test_pass + database: sova_bitrix_test diff --git a/data/mysql-bitrix/init/01-bitrix-schema-and-seed.sql b/data/mysql-bitrix/init/01-bitrix-schema-and-seed.sql new file mode 100644 index 0000000..99b45c4 --- /dev/null +++ b/data/mysql-bitrix/init/01-bitrix-schema-and-seed.sql @@ -0,0 +1,67 @@ +DROP TABLE IF EXISTS b_iblock_element_property; +DROP TABLE IF EXISTS b_iblock_property; +DROP TABLE IF EXISTS b_iblock_element; +DROP TABLE IF EXISTS b_file; + +CREATE TABLE b_file ( + ID INT PRIMARY KEY, + SUBDIR VARCHAR(255), + FILE_NAME VARCHAR(255) +) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; + +CREATE TABLE b_iblock_element ( + ID INT PRIMARY KEY, + IBLOCK_ID INT, + IBLOCK_SECTION_ID INT NULL, + WF_PARENT_ELEMENT_ID INT NULL, + XML_ID VARCHAR(255) NULL, + NAME VARCHAR(255), + ACTIVE CHAR(1) DEFAULT 'Y', + CODE VARCHAR(255), + PREVIEW_PICTURE INT NULL, + PREVIEW_TEXT TEXT, + DETAIL_TEXT TEXT, + DATE_CREATE DATETIME DEFAULT CURRENT_TIMESTAMP, + TIMESTAMP_X DATETIME DEFAULT CURRENT_TIMESTAMP +) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; + +CREATE TABLE b_iblock_property ( + ID INT PRIMARY KEY, + IBLOCK_ID INT, + NAME VARCHAR(255), + CODE VARCHAR(255), + ACTIVE CHAR(1) DEFAULT 'Y' +) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; + +CREATE TABLE b_iblock_element_property ( + ID INT PRIMARY KEY AUTO_INCREMENT, + IBLOCK_PROPERTY_ID INT, + IBLOCK_ELEMENT_ID INT, + VALUE TEXT, + INDEX idx_element (IBLOCK_ELEMENT_ID), + INDEX idx_property (IBLOCK_PROPERTY_ID) +) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; + +INSERT INTO b_file (ID, SUBDIR, FILE_NAME) +VALUES (1, 'local', 'doctor.png'); + +INSERT INTO b_iblock_element (ID, IBLOCK_ID, XML_ID, NAME, ACTIVE, CODE, PREVIEW_PICTURE, PREVIEW_TEXT, DETAIL_TEXT) +VALUES + (1001, 91, '101', 'Иванов Иван Иванович', 'Y', 'ivanov-ivan', 1, 'Тестовый врач Bitrix', 'Локальное описание врача из Bitrix'), + (2001, 91, 'review-1', 'Local review', 'Y', 'local-review', NULL, 'Отзыв', 'Отзыв из локального Bitrix'); + +INSERT INTO b_iblock_property (ID, IBLOCK_ID, NAME, CODE, ACTIVE) +VALUES + (1, 91, 'Связанный врач', 'MEDIC', 'Y'), + (2, 91, 'Текст отзыва', 'MESSAGE', 'Y'), + (3, 91, 'Код услуги', 'KOD', 'Y'), + (4, 91, 'Отзывы', 'LINK_REVIEWS', 'Y'), + (5, 91, 'Прайс', 'LINK_PRICE_1', 'Y'); + +INSERT INTO b_iblock_element_property (IBLOCK_PROPERTY_ID, IBLOCK_ELEMENT_ID, VALUE) +VALUES + (1, 2001, '1001'), + (2, 2001, 'Локальный отзыв из Bitrix'), + (3, 1001, '1001'), + (4, 1001, '2001'), + (5, 1001, '1001'); diff --git a/data/mysql-simple/mysql.yaml b/data/mysql-simple/mysql.yaml new file mode 100644 index 0000000..da10c12 --- /dev/null +++ b/data/mysql-simple/mysql.yaml @@ -0,0 +1,48 @@ +apiVersion: v1 +kind: Service +metadata: + name: mysql-bitrix-test + namespace: sova-data-test +spec: + ports: + - port: 3306 + targetPort: 3306 + selector: + app: mysql-bitrix-test +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: mysql-bitrix-test + namespace: sova-data-test +spec: + replicas: 1 + selector: + matchLabels: + app: mysql-bitrix-test + template: + metadata: + labels: + app: mysql-bitrix-test + spec: + containers: + - name: mysql + image: mysql:8.0 + args: + - --default-authentication-plugin=mysql_native_password + env: + - name: MYSQL_ROOT_PASSWORD + value: bitrix_root_test + - name: MYSQL_DATABASE + value: sova_bitrix_test + - name: MYSQL_USER + value: bitrix_test + - name: MYSQL_PASSWORD + value: bitrix_test_pass + ports: + - containerPort: 3306 + resources: + requests: + memory: 256Mi + limits: + memory: 512Mi diff --git a/data/postgres/init/01-create-databases.sql b/data/postgres/init/01-create-databases.sql new file mode 100644 index 0000000..ad76497 --- /dev/null +++ b/data/postgres/init/01-create-databases.sql @@ -0,0 +1 @@ +CREATE DATABASE sova_cabinet_local OWNER sova_local; diff --git a/data/postgres/init/02-backend-schema-and-seed.sql b/data/postgres/init/02-backend-schema-and-seed.sql new file mode 100644 index 0000000..56544b0 --- /dev/null +++ b/data/postgres/init/02-backend-schema-and-seed.sql @@ -0,0 +1,509 @@ +\connect sova_backend_local + +DROP SCHEMA public CASCADE; +CREATE SCHEMA public; +GRANT ALL ON SCHEMA public TO sova_local; + +CREATE TABLE users ( + id INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + uid INTEGER NOT NULL UNIQUE, + email VARCHAR(180), + roles JSONB NOT NULL DEFAULT '[]', + region_id INTEGER NOT NULL DEFAULT 91, + password VARCHAR(255) NOT NULL, + birth_date DATE, + logged_in TIMESTAMP +); + +CREATE TABLE departments ( + id INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + did BIGINT NOT NULL UNIQUE, + name VARCHAR(255) NOT NULL, + online_mode BOOLEAN NOT NULL DEFAULT true, + alias VARCHAR(255) NOT NULL, + active BOOLEAN NOT NULL DEFAULT true, + group_name VARCHAR(255) +); + +CREATE TABLE filial ( + id INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + fid INTEGER NOT NULL UNIQUE, + name VARCHAR(255) NOT NULL, + address VARCHAR(255), + region_id INTEGER, + site_id INTEGER, + active BOOLEAN NOT NULL DEFAULT true, + company VARCHAR(255), + short_name VARCHAR(255), + phone VARCHAR(255), + policy TEXT, + picture VARCHAR(255), + email VARCHAR(255), + origin VARCHAR(255) +); + +CREATE TABLE specialist ( + id INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + name VARCHAR(255) NOT NULL, + preview_picture VARCHAR(255), + active BOOLEAN NOT NULL DEFAULT true, + display_schedule BOOLEAN NOT NULL DEFAULT true, + dcodes VARCHAR(255), + region_id INTEGER, + alias VARCHAR(255) NOT NULL, + post VARCHAR(255), + experience VARCHAR(255), + s_type INTEGER, + update_at TIMESTAMP NOT NULL DEFAULT now(), + anons TEXT, + content TEXT, + tags JSONB, + highlighted_tags JSONB, + video VARCHAR(255), + video_vertical VARCHAR(255), + schedule_text VARCHAR(255), + category VARCHAR(255), + patient_age INTEGER, + kodoper JSONB, + only_online_mode BOOLEAN, + prodoctor BOOLEAN, + prodoctor_text VARCHAR(255), + prodoctor_link VARCHAR(255), + degree VARCHAR(255), + kiosk BOOLEAN NOT NULL DEFAULT false, + filials JSONB, + accepts_dms BOOLEAN, + specialities JSONB +); + +CREATE TABLE location ( + id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + dcode BIGINT, + department BIGINT NOT NULL, + filial INTEGER NOT NULL, + online_mode BOOLEAN NOT NULL DEFAULT true, + active BOOLEAN NOT NULL DEFAULT true, + nearest_date DATE, + specialist_id INTEGER REFERENCES specialist(id) ON DELETE CASCADE +); + +CREATE TABLE review ( + id INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + specialist_id INTEGER REFERENCES specialist(id) ON DELETE CASCADE, + active BOOLEAN NOT NULL DEFAULT true, + date_create DATE NOT NULL DEFAULT CURRENT_DATE, + message TEXT NOT NULL, + author VARCHAR(255) NOT NULL, + rating DOUBLE PRECISION NOT NULL DEFAULT 5, + source VARCHAR(255), + external_id INTEGER +); + +CREATE TABLE specialist_docs ( + id INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + specialist_id INTEGER REFERENCES specialist(id) ON DELETE CASCADE, + name VARCHAR(255) NOT NULL, + description VARCHAR(255), + picture VARCHAR(255), + active BOOLEAN NOT NULL DEFAULT true, + type VARCHAR(255) NOT NULL +); + +CREATE TABLE specialist_dcode_description ( + id INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + dcode BIGINT NOT NULL, + department BIGINT, + specialist_id INTEGER NOT NULL REFERENCES specialist(id) ON DELETE CASCADE, + content TEXT NOT NULL, + create_at TIMESTAMP NOT NULL DEFAULT now(), + update_at TIMESTAMP NOT NULL DEFAULT now() +); + +CREATE TABLE stock ( + id INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + name VARCHAR(255) NOT NULL, + content TEXT NOT NULL, + picture VARCHAR(255), + anons TEXT, + start_date TIMESTAMP NOT NULL DEFAULT now(), + end_date TIMESTAMP NOT NULL DEFAULT now() + interval '30 days' +); + +CREATE TABLE stock_specialist ( + stock_id INTEGER NOT NULL REFERENCES stock(id) ON DELETE CASCADE, + specialist_id INTEGER NOT NULL REFERENCES specialist(id) ON DELETE CASCADE, + PRIMARY KEY (stock_id, specialist_id) +); + +CREATE TABLE price_department ( + id INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + name VARCHAR(255) NOT NULL, + group_id INTEGER NOT NULL, + doct_count INTEGER DEFAULT 0, + view_in_web BOOLEAN DEFAULT true +); + +CREATE TABLE price_list ( + id INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + kodoper INTEGER, + schname VARCHAR(255), + specname VARCHAR(255), + speccode INTEGER, + price_info JSONB, + discprice NUMERIC(10,2), + structname VARCHAR(255), + fname VARCHAR(255), + filial INTEGER, + comment TEXT, + media_id INTEGER, + date_update TIMESTAMP DEFAULT now(), + group_id INTEGER, + discpercent INTEGER +); + +CREATE TABLE schedule ( + id INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + dcode BIGINT, + department BIGINT, + filial INTEGER, + schedident BIGINT, + workdate DATE, + rnum VARCHAR(255), + rfloor VARCHAR(255), + rbuilding VARCHAR(255), + time JSONB, + is_free BOOLEAN DEFAULT true, + online_mode BOOLEAN DEFAULT false, + query_string TEXT, + created_at TIMESTAMP DEFAULT now(), + interval_is_free BOOLEAN DEFAULT true, + price_info NUMERIC(10,2) +); + +CREATE TABLE record ( + id INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + specialist_id INTEGER NOT NULL, + phone VARCHAR(255) NOT NULL, + create_at TIMESTAMP NOT NULL DEFAULT now(), + hash VARCHAR(255) NOT NULL, + reserve JSONB NOT NULL DEFAULT '{}' +); + +CREATE TABLE alert_sms ( + id INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + record_id INTEGER UNIQUE REFERENCES record(id) ON DELETE CASCADE, + date_create TIMESTAMP NOT NULL DEFAULT now(), + response TEXT NOT NULL +); + +CREATE TABLE widget_form ( + id INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + name VARCHAR(255) NOT NULL +); + +CREATE TABLE widget_form_input ( + id INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + text VARCHAR(255) NOT NULL, + type VARCHAR(255) NOT NULL, + bitrix24_id VARCHAR(255) NOT NULL, + widget_form_id INTEGER NOT NULL REFERENCES widget_form(id) ON DELETE CASCADE, + sort INTEGER NOT NULL DEFAULT 100 +); + +CREATE TABLE article ( + id INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + name TEXT, + preview_picture TEXT, + active BOOLEAN DEFAULT true, + doctors JSONB, + services JSONB, + region_id INTEGER, + alias TEXT, + anons TEXT, + content TEXT, + update_at TIMESTAMP DEFAULT now() +); + +CREATE TABLE disease ( + id INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + name VARCHAR(255), + preview_picture VARCHAR(255), + active BOOLEAN DEFAULT true, + region_id INTEGER, + alias VARCHAR(255), + anons TEXT, + update_at TIMESTAMP DEFAULT now(), + hide_picture BOOLEAN, + read_time TEXT, + diseases_name TEXT, + tags_important JSONB, + tags JSONB, + diseases_other_name TEXT, + symptom TEXT, + staff TEXT, + link_services JSONB, + staff_list JSONB, + staff_post JSONB, + staff_post_exclude JSONB, + link_faq JSONB, + bibliography TEXT, + staff_check JSONB, + content TEXT +); + +CREATE TABLE medical_center ( + id INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + name VARCHAR(255), + active BOOLEAN DEFAULT true, + region_id INTEGER, + alias VARCHAR(255), + anons TEXT, + content TEXT, + update_at TIMESTAMP DEFAULT now(), + kod_uslug JSONB, + doctors JSONB, + services JSONB, + articles JSONB, + txt_up JSONB, + main_link_staff TEXT, + contraindications JSONB, + hide_picture INTEGER, + indications JSONB, + link_sale JSONB, + plus_list JSONB, + plus_text TEXT, + plus_title TEXT, + process_text TEXT, + process_title TEXT, + services_list JSONB, + services_photos JSONB, + services_title TEXT, + sort_staff JSONB, + training_text TEXT, + training_text_title TEXT, + why_text TEXT, + why_title TEXT +); + +CREATE TABLE news ( + id INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + name VARCHAR(255), + active BOOLEAN DEFAULT true, + region_id INTEGER, + alias VARCHAR(255), + anons TEXT, + content TEXT, + update_at TIMESTAMP DEFAULT now(), + link_el_price TEXT, + short_name TEXT, + timer TEXT, + timer_bg TEXT, + form_order JSONB, + link_services JSONB, + link_staff JSONB, + photos JSONB +); + +CREATE TABLE promo ( + id INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + name VARCHAR(255), + active BOOLEAN DEFAULT true, + region_id INTEGER, + alias VARCHAR(255), + anons TEXT, + content TEXT, + update_at TIMESTAMP DEFAULT now(), + clinics JSONB, + timer TEXT, + timer_bg TEXT, + short_name TEXT, + link_services JSONB, + link_staff JSONB, + period VARCHAR(255), + photos JSONB +); + +CREATE TABLE site_services ( + id INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + name VARCHAR(255), + active BOOLEAN DEFAULT true, + region_id INTEGER, + alias VARCHAR(255), + anons TEXT, + content TEXT, + update_at TIMESTAMP DEFAULT now(), + link_videoreviews JSONB, + preview_img TEXT, + faq JSONB, + part_price TEXT, + pokazaniya TEXT, + preparation TEXT, + protivopokazaniya TEXT, + hide_sign_btn JSONB, + quiz JSONB, + tags JSONB, + tags_important JSONB, + banner_img TEXT, + banner_img_m TEXT, + banner_img_url TEXT, + clinics JSONB, + download_file TEXT, + full_width_banner TEXT, + staff_up JSONB, + advantages JSONB, + hide_picture INTEGER, + kod_uslug TEXT, + link_price TEXT, + photos_title TEXT, + sale_id JSONB, + sort_staff JSONB, + contraindications_list TEXT, + custom_block_text TEXT, + custom_block_text2 TEXT, + custom_block_title TEXT, + custom_block_title2 TEXT, + indications_list TEXT, + link_articles_services JSONB, + plus_list TEXT, + plus_text TEXT, + plus_title TEXT, + prepare_title TEXT, + process_text TEXT, + process_title TEXT, + services_list TEXT, + services_photos JSONB, + services_title TEXT, + text_up TEXT, + training_text TEXT, + why_text TEXT, + why_title TEXT, + link_faq JSONB, + link_services JSONB, + link_staff JSONB, + photos JSONB +); + +CREATE TABLE web_get_docinfo ( + id INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + source_table VARCHAR(255), + doc_name VARCHAR(255), + doc_post VARCHAR(255), + filial INTEGER, + viewinweb BOOLEAN, + depnum INTEGER, + first_schid INTEGER, + second_schid INTEGER, + accepts_dms BOOLEAN, + anons TEXT, + content TEXT, + updated_at TIMESTAMP DEFAULT now() +); + +CREATE TABLE idoctor ( + id INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + dcode INTEGER, + name VARCHAR(255), + department INTEGER, + filial INTEGER, + nearest_date DATE, + online_mode BOOLEAN DEFAULT true, + updated TIMESTAMP DEFAULT now() +); + +INSERT INTO users (uid, email, roles, region_id, password, birth_date) +VALUES (100001, md5('local.backend@example.test'), '["ROLE_USER","ROLE_ADMIN"]', 91, '$2y$13$Y98kYF03yQjzDo0HsvvWMu..4SqB3Kgv2d8GNf870MEjJbXUJ2i.a', '1990-01-01'); + +INSERT INTO departments (did, name, online_mode, alias, group_name) +VALUES (10, 'Терапия', true, 'terapiya', 'Взрослые специалисты'); + +INSERT INTO filial (fid, name, address, region_id, site_id, company, short_name, phone, email) +VALUES + (1, 'Сова Саратов', 'Localhost, 1', 91, 1, 'ООО Local Clinic', 'Саратов', '+70000000001', 'saratov@example.test'), + (2, 'Сова Волгоград', 'Localhost, 2', 92, 2, 'ООО Local Clinic', 'Волгоград', '+70000000002', 'volgograd@example.test'), + (3, 'Сова Воронеж', 'Localhost, 3', 93, 3, 'ООО Local Clinic', 'Воронеж', '+70000000003', 'voronezh@example.test'), + (4, 'Сова Краснодар', 'Localhost, 4', 94, 4, 'ООО Local Clinic', 'Краснодар', '+70000000004', 'krasnodar@example.test'); + +INSERT INTO specialist (name, active, display_schedule, dcodes, region_id, alias, post, experience, s_type, anons, content, kodoper, filials, accepts_dms, specialities) +VALUES ('Иванов Иван Иванович', true, true, '101', 91, 'ivanov-ivan', 'Врач-терапевт', '2014', 1, 'Тестовый врач', 'Тестовое описание врача', '[1001]', '[1]', true, '["Терапия"]'); + +INSERT INTO location (dcode, department, filial, online_mode, active, nearest_date, specialist_id) +VALUES (101, 10, 1, true, true, CURRENT_DATE + interval '1 day', 1); + +INSERT INTO review (specialist_id, message, author, rating, source, external_id) +VALUES (1, 'Тестовый отзыв для локальной базы', 'Пациент Local', 5, 'local', 1); + +INSERT INTO specialist_docs (specialist_id, name, active, type) +VALUES (1, 'Тестовый сертификат', true, 'certificate'); + +INSERT INTO specialist_dcode_description (dcode, department, specialist_id, content) +VALUES (101, 10, 1, 'Локальное описание врача по dcode.'); + +INSERT INTO stock (name, content, anons) +VALUES ('Local акция', 'Тестовая акция только для локальной разработки', 'Local'); + +INSERT INTO stock_specialist (stock_id, specialist_id) VALUES (1, 1); + +INSERT INTO price_department (name, group_id, doct_count, view_in_web) +VALUES ('Консультации', 100, 1, true); + +INSERT INTO price_list (kodoper, schname, specname, speccode, price_info, discprice, structname, fname, filial, group_id) +VALUES (1001, 'Прием терапевта', 'Иванов Иван Иванович', 101, '{"base":1500,"discount":1200}', 1200, 'Терапия', 'Сова Local', 1, 100); + +INSERT INTO schedule (dcode, department, filial, schedident, workdate, time, is_free, online_mode, price_info) +VALUES (101, 10, 1, 555001, CURRENT_DATE + interval '1 day', '[{"st":"09:00","en":"09:30"}]', true, true, 1500); + +INSERT INTO record (specialist_id, phone, hash, reserve) +VALUES (1, '+70000000000', md5('+70000000000'), '{"local":true,"date":"tomorrow"}'); + +INSERT INTO alert_sms (record_id, response) +VALUES (1, '{"status":"local-ok"}'); + +INSERT INTO widget_form (name) VALUES ('Local форма'); +INSERT INTO widget_form_input (text, type, bitrix24_id, widget_form_id, sort) +VALUES ('Телефон', 'phone', 'PHONE', 1, 10); + +INSERT INTO article (name, active, region_id, alias, anons, content) +VALUES ('Local статья', true, 91, 'local-article', 'Анонс', 'Контент локальной статьи'); + +INSERT INTO disease (name, active, region_id, alias, anons, content) +VALUES ('Local заболевание', true, 91, 'local-disease', 'Анонс', 'Описание'); + +INSERT INTO medical_center (name, active, region_id, alias, anons, content) +VALUES ('Local медцентр', true, 91, 'local-center', 'Анонс', 'Описание'); + +INSERT INTO news (name, active, region_id, alias, anons, content) +VALUES ('Local новость', true, 91, 'local-news', 'Анонс', 'Контент'); + +INSERT INTO promo (name, active, region_id, alias, anons, content, period) +VALUES ('Local промо', true, 91, 'local-promo', 'Анонс', 'Контент', 'Всегда'); + +INSERT INTO site_services (name, active, region_id, alias, anons, content, tags) +VALUES ('Local услуга', true, 91, 'local-service', 'Анонс', 'Контент', '["local"]'); + +INSERT INTO web_get_docinfo (source_table, doc_name, doc_post, filial, viewinweb, depnum, accepts_dms, anons, content) +VALUES ('local', 'Иванов Иван Иванович', 'Врач-терапевт', 1, true, 10, true, 'Анонс', 'Описание'); + +INSERT INTO idoctor (dcode, name, department, filial, nearest_date, online_mode) +VALUES (101, 'Иванов Иван Иванович', 10, 1, CURRENT_DATE + interval '1 day', true); + +-- После seed INSERT sequence identity должен указывать на MAX(id), иначе CREATE вернёт duplicate key id=1. +DO $body$ +DECLARE + tbl text; +BEGIN + FOREACH tbl IN ARRAY ARRAY[ + 'users', 'departments', 'filial', 'specialist', 'location', 'review', + 'specialist_docs', 'specialist_dcode_description', 'stock', + 'price_department', 'price_list', 'schedule', 'record', 'alert_sms', + 'widget_form', 'widget_form_input', 'article', 'disease', 'medical_center', + 'news', 'promo', 'site_services', 'web_get_docinfo', 'idoctor' + ] + LOOP + EXECUTE format( + 'SELECT setval(pg_get_serial_sequence(%L, ''id''), COALESCE((SELECT MAX(id) FROM %I), 1), true)', + tbl, + tbl + ); + END LOOP; +END +$body$; diff --git a/data/postgres/init/03-cabinet-schema-and-seed.sql b/data/postgres/init/03-cabinet-schema-and-seed.sql new file mode 100644 index 0000000..324e5b1 --- /dev/null +++ b/data/postgres/init/03-cabinet-schema-and-seed.sql @@ -0,0 +1,296 @@ +\connect sova_cabinet_local + +DROP SCHEMA public CASCADE; +CREATE SCHEMA public; +GRANT ALL ON SCHEMA public TO sova_local; + +CREATE TABLE users ( + id INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + email VARCHAR(180), + roles JSONB NOT NULL DEFAULT '[]', + password VARCHAR(255), + uid INTEGER NOT NULL UNIQUE, + token VARCHAR(255), + full_name VARCHAR(255) NOT NULL, + phone VARCHAR(255), + confirm BOOLEAN NOT NULL DEFAULT true, + created_at TIMESTAMP DEFAULT now(), + last_activity_at TIMESTAMP DEFAULT now() +); + +CREATE TABLE city ( + id INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + name VARCHAR(255) NOT NULL, + region_id INTEGER NOT NULL, + time_zone INTEGER NOT NULL DEFAULT 4 +); + +CREATE TABLE filial ( + id INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + fid INTEGER NOT NULL, + name VARCHAR(255) NOT NULL, + address VARCHAR(255) NOT NULL, + address_name VARCHAR(255), + site_id INTEGER, + city_id INTEGER REFERENCES city(id) ON DELETE SET NULL, + active BOOLEAN NOT NULL DEFAULT true, + company VARCHAR(255) +); + +CREATE TABLE banner ( + id INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + href VARCHAR(255) NOT NULL, + src VARCHAR(255) NOT NULL, + active BOOLEAN NOT NULL DEFAULT true, + city_id INTEGER UNIQUE REFERENCES city(id) ON DELETE CASCADE +); + +CREATE TABLE review_source ( + id INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + city_id INTEGER NOT NULL REFERENCES city(id) ON DELETE CASCADE, + name VARCHAR(255) NOT NULL, + count_row INTEGER NOT NULL DEFAULT 0, + active BOOLEAN NOT NULL DEFAULT true, + rating DOUBLE PRECISION NOT NULL DEFAULT 5, + filial_id INTEGER REFERENCES filial(id) ON DELETE SET NULL, + date_create DATE NOT NULL DEFAULT CURRENT_DATE +); + +CREATE TABLE category_page ( + id INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + name VARCHAR(255) NOT NULL, + active BOOLEAN NOT NULL DEFAULT true +); + +CREATE TABLE page ( + id INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + name VARCHAR(255) NOT NULL, + description TEXT NOT NULL, + active BOOLEAN NOT NULL DEFAULT true, + alias VARCHAR(255) NOT NULL, + category_id INTEGER NOT NULL REFERENCES category_page(id) ON DELETE CASCADE +); + +CREATE TABLE department ( + id INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + did INTEGER NOT NULL, + name VARCHAR(255) NOT NULL, + group_name VARCHAR(255) NOT NULL, + online_mode BOOLEAN NOT NULL DEFAULT true, + alias VARCHAR(255) NOT NULL, + active BOOLEAN NOT NULL DEFAULT true, + middle_name VARCHAR(255) +); + +CREATE TABLE price_department ( + id INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + name VARCHAR(255) NOT NULL, + group_id INTEGER NOT NULL, + group_name VARCHAR(255), + doct_count INTEGER DEFAULT 0, + view_in_web BOOLEAN DEFAULT true +); + +CREATE TABLE price_list_view ( + id INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + kodoper INTEGER, + schname VARCHAR(255), + specname VARCHAR(255), + speccode INTEGER, + price_info JSONB, + discpercent INTEGER, + discprice NUMERIC(10,2), + structname VARCHAR(255), + fname VARCHAR(255), + filial INTEGER, + comment TEXT, + media_id INTEGER, + date_update TIMESTAMP DEFAULT now(), + group_id INTEGER +); + +CREATE TABLE price ( + id INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + name VARCHAR(255), + value NUMERIC(10,2), + property_value_id INTEGER, + date_update TIMESTAMP DEFAULT now() +); + +CREATE TABLE specialist_view ( + id INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + name VARCHAR(255) NOT NULL, + kinder INTEGER, + speciality VARCHAR(255), + category VARCHAR(255), + experience VARCHAR(255), + description TEXT, + infoclinica BOOLEAN DEFAULT true, + alias VARCHAR(255) NOT NULL, + dcode INTEGER NOT NULL, + s_type INTEGER, + active BOOLEAN DEFAULT true, + region_id INTEGER, + kodoper JSONB, + updated TIMESTAMP DEFAULT now(), + accepts_dms BOOLEAN DEFAULT true, + degree VARCHAR(255) +); + +CREATE TABLE location_view ( + id INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + dcode INTEGER NOT NULL, + department INTEGER NOT NULL, + filial INTEGER NOT NULL, + specialist_id INTEGER NOT NULL, + online_mode BOOLEAN NOT NULL DEFAULT true, + active BOOLEAN NOT NULL DEFAULT true, + nearest_date DATE +); + +CREATE TABLE remote_review ( + id INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + external_id INTEGER, + specialist_id INTEGER, + active BOOLEAN DEFAULT true, + date_create DATE DEFAULT CURRENT_DATE, + message TEXT, + author VARCHAR(255), + rating DOUBLE PRECISION DEFAULT 5, + source VARCHAR(255) +); + +CREATE TABLE record ( + id INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + specialist_id INTEGER NOT NULL, + phone VARCHAR(255) NOT NULL, + create_at TIMESTAMP NOT NULL DEFAULT now(), + hash VARCHAR(255) NOT NULL, + reserve JSONB NOT NULL DEFAULT '{}' +); + +CREATE TABLE alert_sms ( + id INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + record_id INTEGER UNIQUE REFERENCES record(id) ON DELETE CASCADE, + date_create TIMESTAMP NOT NULL DEFAULT now(), + response TEXT NOT NULL +); + +CREATE TABLE widget_form ( + id INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + name VARCHAR(255) NOT NULL +); + +CREATE TABLE widget_form_input ( + id INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + text VARCHAR(255) NOT NULL, + type VARCHAR(255) NOT NULL, + bitrix24_id VARCHAR(255) NOT NULL, + widget_form_id INTEGER REFERENCES widget_form(id) ON DELETE CASCADE, + sort INTEGER NOT NULL DEFAULT 100 +); + +CREATE TABLE usrlog ( + id INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + pcode INTEGER, + agent TEXT, + client_ip VARCHAR(255), + method VARCHAR(255), + created_at TIMESTAMP DEFAULT now() +); + +CREATE TABLE direct_company ( + id INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + name VARCHAR(255), + company_id BIGINT, + city VARCHAR(255) +); + +CREATE TABLE direct_report ( + id INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + date DATE, + ad_group_id BIGINT, + campaign_id BIGINT, + ad_id BIGINT, + impressions INTEGER, + clicks INTEGER, + cost DOUBLE PRECISION, + conversions INTEGER +); + +INSERT INTO users (email, roles, password, uid, token, full_name, phone, confirm) +VALUES ( + '6c6f63616c2e636162696e6574406578616d706c652e74657374', + '["ROLE_USER","ROLE_ADMIN"]', + '$2y$12$hqHoZsKN01W.IBcfZYRf.OygGbGIMM7RW0M8fZxo.DNjswjj07S2u', + 200001, + 'Yjd4N6Xlvfay4sNPfPf6PBeosTdmpfCl6+xg9a9V7BnHmfocaw6YSD4NF6Vrvqrm9+nwzNsm5KzpoFV23nG8Lw==', + 'qpHB5XVk6VcuthTcmGV7zqBFN805ejONu+ciwz5nwC4AyEjJ0oH7Ci5ISfgpvwbn2NhLHyTA5tCnN2jd4qQogQ==', + '2I/vmVgNZC98ben0LPkqxmZX1oiAP/k+aXCn3+/dxTBCPBlN7VLR9uiSoWcOuxeBi2rAzfl9t1N1b/PJkJO6MQ==', + true +); + +INSERT INTO city (name, region_id, time_zone) +VALUES + ('Саратов Local', 91, 4), + ('Волгоград Local', 92, 3), + ('Воронеж Local', 93, 3), + ('Краснодар Local', 94, 3); + +INSERT INTO filial (fid, name, address, address_name, site_id, city_id, company) +VALUES + (1, 'Сова Саратов', 'Localhost, 1', 'Саратов', 1, 1, 'ООО Local Clinic'), + (2, 'Сова Волгоград', 'Localhost, 2', 'Волгоград', 2, 2, 'ООО Local Clinic'), + (3, 'Сова Воронеж', 'Localhost, 3', 'Воронеж', 3, 3, 'ООО Local Clinic'), + (4, 'Сова Краснодар', 'Localhost, 4', 'Краснодар', 4, 4, 'ООО Local Clinic'); + +INSERT INTO banner (href, src, city_id) +VALUES ('http://localhost:8082', '/banners/local.png', 1); + +INSERT INTO review_source (city_id, name, count_row, rating, filial_id) +VALUES (1, 'Local Reviews', 1, 5, 1); + +INSERT INTO category_page (name, active) VALUES ('Local категория', true); +INSERT INTO page (name, description, active, alias, category_id) +VALUES ('Local страница', 'Контент локальной страницы', true, 'local-page', 1); + +INSERT INTO department (did, name, group_name, online_mode, alias, middle_name) +VALUES (10, 'Терапия', 'Взрослые специалисты', true, 'terapiya', 'терапевта'); + +INSERT INTO price_department (name, group_id, group_name, doct_count, view_in_web) +VALUES ('Консультации', 100, 'Врачи', 1, true); + +INSERT INTO specialist_view (name, kinder, speciality, category, experience, description, alias, dcode, s_type, active, region_id, kodoper, accepts_dms, degree) +VALUES ('Иванов Иван Иванович', 0, 'Терапевт', 'Первая категория', '12', 'Локальный врач', 'ivanov-ivan', 101, 1, true, 91, '[1001]', true, 'к.м.н.'); + +INSERT INTO location_view (dcode, department, filial, specialist_id, online_mode, active, nearest_date) +VALUES (101, 10, 1, 1, true, true, CURRENT_DATE + interval '1 day'); + +INSERT INTO price_list_view (kodoper, schname, specname, speccode, price_info, discpercent, discprice, structname, fname, filial, group_id) +VALUES (1001, 'Прием терапевта', 'Иванов Иван Иванович', 101, '{"base":1500,"discount":1200}', 10, 1200, 'Терапия', 'Сова Local', 1, 100); + +INSERT INTO remote_review (external_id, specialist_id, message, author, rating, source) +VALUES (1, 1, 'Тестовый отзыв для локальной базы', 'Пациент Local', 5, 'local'); + +INSERT INTO record (specialist_id, phone, hash, reserve) +VALUES (1, '+70000000000', md5('+70000000000'), '{"local":true}'); + +INSERT INTO alert_sms (record_id, response) +VALUES (1, '{"status":"local-ok"}'); + +INSERT INTO widget_form (id, name) OVERRIDING SYSTEM VALUE VALUES + (1, 'Local форма'), + (2, 'Вызов врача на дом'); + +INSERT INTO widget_form_input (text, type, bitrix24_id, widget_form_id, sort) VALUES + ('Телефон', 'phone', 'PHONE', 1, 10), + ('ФИО пациента', 'text', 'NAME', 2, 10), + ('Телефон', 'phone', 'PHONE', 2, 20), + ('Адрес выезда', 'text', 'ADDRESS', 2, 30), + ('Комментарий / симптомы', 'textarea', 'COMMENTS', 2, 40); + +SELECT setval(pg_get_serial_sequence('widget_form', 'id'), (SELECT MAX(id) FROM widget_form)); +SELECT setval(pg_get_serial_sequence('widget_form_input', 'id'), (SELECT MAX(id) FROM widget_form_input)); + +INSERT INTO usrlog (pcode, agent, client_ip, method) +VALUES (200001, 'local-agent', '127.0.0.1', 'seed'); diff --git a/data/test/Chart.yaml b/data/test/Chart.yaml new file mode 100644 index 0000000..da7b2e4 --- /dev/null +++ b/data/test/Chart.yaml @@ -0,0 +1,19 @@ +apiVersion: v2 +name: sova-data-test +description: PostgreSQL, MySQL Bitrix, Redis for test +type: application +version: 0.1.0 + +dependencies: + - name: postgresql + version: 15.5.38 + repository: https://charts.bitnami.com/bitnami + condition: postgresql.enabled + - name: mysql + version: 11.4.4 + repository: https://charts.bitnami.com/bitnami + condition: mysql.enabled + - name: redis + version: 20.6.3 + repository: https://charts.bitnami.com/bitnami + condition: redis.enabled diff --git a/data/test/sql/mysql-bitrix/schema/01-bitrix-schema.sql b/data/test/sql/mysql-bitrix/schema/01-bitrix-schema.sql new file mode 100644 index 0000000..7874eea --- /dev/null +++ b/data/test/sql/mysql-bitrix/schema/01-bitrix-schema.sql @@ -0,0 +1,44 @@ +DROP TABLE IF EXISTS b_iblock_element_property; +DROP TABLE IF EXISTS b_iblock_property; +DROP TABLE IF EXISTS b_iblock_element; +DROP TABLE IF EXISTS b_file; + +CREATE TABLE b_file ( + ID INT PRIMARY KEY, + SUBDIR VARCHAR(255), + FILE_NAME VARCHAR(255) +) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; + +CREATE TABLE b_iblock_element ( + ID INT PRIMARY KEY, + IBLOCK_ID INT, + IBLOCK_SECTION_ID INT NULL, + WF_PARENT_ELEMENT_ID INT NULL, + XML_ID VARCHAR(255) NULL, + NAME VARCHAR(255), + ACTIVE CHAR(1) DEFAULT 'Y', + CODE VARCHAR(255), + PREVIEW_PICTURE INT NULL, + PREVIEW_TEXT TEXT, + DETAIL_TEXT TEXT, + DATE_CREATE DATETIME DEFAULT CURRENT_TIMESTAMP, + TIMESTAMP_X DATETIME DEFAULT CURRENT_TIMESTAMP +) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; + +CREATE TABLE b_iblock_property ( + ID INT PRIMARY KEY, + IBLOCK_ID INT, + NAME VARCHAR(255), + CODE VARCHAR(255), + ACTIVE CHAR(1) DEFAULT 'Y' +) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; + +CREATE TABLE b_iblock_element_property ( + ID INT PRIMARY KEY AUTO_INCREMENT, + IBLOCK_PROPERTY_ID INT, + IBLOCK_ELEMENT_ID INT, + VALUE TEXT, + INDEX idx_element (IBLOCK_ELEMENT_ID), + INDEX idx_property (IBLOCK_PROPERTY_ID) +) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; + diff --git a/data/test/sql/mysql-bitrix/seed/01-bitrix-seed.sql b/data/test/sql/mysql-bitrix/seed/01-bitrix-seed.sql new file mode 100644 index 0000000..01583b5 --- /dev/null +++ b/data/test/sql/mysql-bitrix/seed/01-bitrix-seed.sql @@ -0,0 +1,23 @@ +INSERT INTO b_file (ID, SUBDIR, FILE_NAME) +VALUES (1, 'local', 'doctor.png'); + +INSERT INTO b_iblock_element (ID, IBLOCK_ID, XML_ID, NAME, ACTIVE, CODE, PREVIEW_PICTURE, PREVIEW_TEXT, DETAIL_TEXT) +VALUES + (1001, 91, '101', 'Иванов Иван Иванович', 'Y', 'ivanov-ivan', 1, 'Тестовый врач Bitrix', 'Локальное описание врача из Bitrix'), + (2001, 91, 'review-1', 'Local review', 'Y', 'local-review', NULL, 'Отзыв', 'Отзыв из локального Bitrix'); + +INSERT INTO b_iblock_property (ID, IBLOCK_ID, NAME, CODE, ACTIVE) +VALUES + (1, 91, 'Связанный врач', 'MEDIC', 'Y'), + (2, 91, 'Текст отзыва', 'MESSAGE', 'Y'), + (3, 91, 'Код услуги', 'KOD', 'Y'), + (4, 91, 'Отзывы', 'LINK_REVIEWS', 'Y'), + (5, 91, 'Прайс', 'LINK_PRICE_1', 'Y'); + +INSERT INTO b_iblock_element_property (IBLOCK_PROPERTY_ID, IBLOCK_ELEMENT_ID, VALUE) +VALUES + (1, 2001, '1001'), + (2, 2001, 'Локальный отзыв из Bitrix'), + (3, 1001, '1001'), + (4, 1001, '2001'), + (5, 1001, '1001'); diff --git a/data/test/sql/postgres/schema/01-create-databases.sql b/data/test/sql/postgres/schema/01-create-databases.sql new file mode 100644 index 0000000..8208d88 --- /dev/null +++ b/data/test/sql/postgres/schema/01-create-databases.sql @@ -0,0 +1,2 @@ +SELECT 'CREATE DATABASE sova_cabinet_test OWNER sova_test' +WHERE NOT EXISTS (SELECT FROM pg_database WHERE datname = 'sova_cabinet_test')\gexec diff --git a/data/test/sql/postgres/schema/02-backend-schema.sql b/data/test/sql/postgres/schema/02-backend-schema.sql new file mode 100644 index 0000000..d71cf09 --- /dev/null +++ b/data/test/sql/postgres/schema/02-backend-schema.sql @@ -0,0 +1,412 @@ +\connect sova_backend_test + +DROP SCHEMA public CASCADE; +CREATE SCHEMA public; +GRANT ALL ON SCHEMA public TO sova_test; + +CREATE TABLE users ( + id INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + uid INTEGER NOT NULL UNIQUE, + email VARCHAR(180), + roles JSONB NOT NULL DEFAULT '[]', + region_id INTEGER NOT NULL DEFAULT 91, + password VARCHAR(255) NOT NULL, + birth_date DATE, + logged_in TIMESTAMP +); + +CREATE TABLE departments ( + id INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + did BIGINT NOT NULL UNIQUE, + name VARCHAR(255) NOT NULL, + online_mode BOOLEAN NOT NULL DEFAULT true, + alias VARCHAR(255) NOT NULL, + active BOOLEAN NOT NULL DEFAULT true, + group_name VARCHAR(255) +); + +CREATE TABLE filial ( + id INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + fid INTEGER NOT NULL UNIQUE, + name VARCHAR(255) NOT NULL, + address VARCHAR(255), + region_id INTEGER, + site_id INTEGER, + active BOOLEAN NOT NULL DEFAULT true, + company VARCHAR(255), + short_name VARCHAR(255), + phone VARCHAR(255), + policy TEXT, + picture VARCHAR(255), + email VARCHAR(255), + origin VARCHAR(255) +); + +CREATE TABLE specialist ( + id INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + name VARCHAR(255) NOT NULL, + preview_picture VARCHAR(255), + active BOOLEAN NOT NULL DEFAULT true, + display_schedule BOOLEAN NOT NULL DEFAULT true, + dcodes VARCHAR(255), + region_id INTEGER, + alias VARCHAR(255) NOT NULL, + post VARCHAR(255), + experience VARCHAR(255), + s_type INTEGER, + update_at TIMESTAMP NOT NULL DEFAULT now(), + anons TEXT, + content TEXT, + tags JSONB, + highlighted_tags JSONB, + video VARCHAR(255), + video_vertical VARCHAR(255), + schedule_text VARCHAR(255), + category VARCHAR(255), + patient_age INTEGER, + kodoper JSONB, + only_online_mode BOOLEAN, + prodoctor BOOLEAN, + prodoctor_text VARCHAR(255), + prodoctor_link VARCHAR(255), + degree VARCHAR(255), + kiosk BOOLEAN NOT NULL DEFAULT false, + filials JSONB, + accepts_dms BOOLEAN, + specialities JSONB +); + +CREATE TABLE location ( + id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + dcode BIGINT, + department BIGINT NOT NULL, + filial INTEGER NOT NULL, + online_mode BOOLEAN NOT NULL DEFAULT true, + active BOOLEAN NOT NULL DEFAULT true, + nearest_date DATE, + specialist_id INTEGER REFERENCES specialist(id) ON DELETE CASCADE +); + +CREATE TABLE review ( + id INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + specialist_id INTEGER REFERENCES specialist(id) ON DELETE CASCADE, + active BOOLEAN NOT NULL DEFAULT true, + date_create DATE NOT NULL DEFAULT CURRENT_DATE, + message TEXT NOT NULL, + author VARCHAR(255) NOT NULL, + rating DOUBLE PRECISION NOT NULL DEFAULT 5, + source VARCHAR(255), + external_id INTEGER +); + +CREATE TABLE specialist_docs ( + id INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + specialist_id INTEGER REFERENCES specialist(id) ON DELETE CASCADE, + name VARCHAR(255) NOT NULL, + description VARCHAR(255), + picture VARCHAR(255), + active BOOLEAN NOT NULL DEFAULT true, + type VARCHAR(255) NOT NULL +); + +CREATE TABLE specialist_dcode_description ( + id INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + dcode BIGINT NOT NULL, + department BIGINT, + specialist_id INTEGER NOT NULL REFERENCES specialist(id) ON DELETE CASCADE, + content TEXT NOT NULL, + create_at TIMESTAMP NOT NULL DEFAULT now(), + update_at TIMESTAMP NOT NULL DEFAULT now() +); + +CREATE TABLE stock ( + id INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + name VARCHAR(255) NOT NULL, + content TEXT NOT NULL, + picture VARCHAR(255), + anons TEXT, + start_date TIMESTAMP NOT NULL DEFAULT now(), + end_date TIMESTAMP NOT NULL DEFAULT now() + interval '30 days' +); + +CREATE TABLE stock_specialist ( + stock_id INTEGER NOT NULL REFERENCES stock(id) ON DELETE CASCADE, + specialist_id INTEGER NOT NULL REFERENCES specialist(id) ON DELETE CASCADE, + PRIMARY KEY (stock_id, specialist_id) +); + +CREATE TABLE price_department ( + id INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + name VARCHAR(255) NOT NULL, + group_id INTEGER NOT NULL, + doct_count INTEGER DEFAULT 0, + view_in_web BOOLEAN DEFAULT true +); + +CREATE TABLE price_list ( + id INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + kodoper INTEGER, + schname VARCHAR(255), + specname VARCHAR(255), + speccode INTEGER, + price_info JSONB, + discprice NUMERIC(10,2), + structname VARCHAR(255), + fname VARCHAR(255), + filial INTEGER, + comment TEXT, + media_id INTEGER, + date_update TIMESTAMP DEFAULT now(), + group_id INTEGER, + discpercent INTEGER +); + +CREATE TABLE schedule ( + id INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + dcode BIGINT, + department BIGINT, + filial INTEGER, + schedident BIGINT, + workdate DATE, + rnum VARCHAR(255), + rfloor VARCHAR(255), + rbuilding VARCHAR(255), + time JSONB, + is_free BOOLEAN DEFAULT true, + online_mode BOOLEAN DEFAULT false, + query_string TEXT, + created_at TIMESTAMP DEFAULT now(), + interval_is_free BOOLEAN DEFAULT true, + price_info NUMERIC(10,2) +); + +CREATE TABLE record ( + id INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + specialist_id INTEGER NOT NULL, + phone VARCHAR(255) NOT NULL, + create_at TIMESTAMP NOT NULL DEFAULT now(), + hash VARCHAR(255) NOT NULL, + reserve JSONB NOT NULL DEFAULT '{}' +); + +CREATE TABLE alert_sms ( + id INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + record_id INTEGER UNIQUE REFERENCES record(id) ON DELETE CASCADE, + date_create TIMESTAMP NOT NULL DEFAULT now(), + response TEXT NOT NULL +); + +CREATE TABLE widget_form ( + id INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + name VARCHAR(255) NOT NULL +); + +CREATE TABLE widget_form_input ( + id INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + text VARCHAR(255) NOT NULL, + type VARCHAR(255) NOT NULL, + bitrix24_id VARCHAR(255) NOT NULL, + widget_form_id INTEGER NOT NULL REFERENCES widget_form(id) ON DELETE CASCADE, + sort INTEGER NOT NULL DEFAULT 100 +); + +CREATE TABLE article ( + id INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + name TEXT, + preview_picture TEXT, + active BOOLEAN DEFAULT true, + doctors JSONB, + services JSONB, + region_id INTEGER, + alias TEXT, + anons TEXT, + content TEXT, + update_at TIMESTAMP DEFAULT now() +); + +CREATE TABLE disease ( + id INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + name VARCHAR(255), + preview_picture VARCHAR(255), + active BOOLEAN DEFAULT true, + region_id INTEGER, + alias VARCHAR(255), + anons TEXT, + update_at TIMESTAMP DEFAULT now(), + hide_picture BOOLEAN, + read_time TEXT, + diseases_name TEXT, + tags_important JSONB, + tags JSONB, + diseases_other_name TEXT, + symptom TEXT, + staff TEXT, + link_services JSONB, + staff_list JSONB, + staff_post JSONB, + staff_post_exclude JSONB, + link_faq JSONB, + bibliography TEXT, + staff_check JSONB, + content TEXT +); + +CREATE TABLE medical_center ( + id INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + name VARCHAR(255), + active BOOLEAN DEFAULT true, + region_id INTEGER, + alias VARCHAR(255), + anons TEXT, + content TEXT, + update_at TIMESTAMP DEFAULT now(), + kod_uslug JSONB, + doctors JSONB, + services JSONB, + articles JSONB, + txt_up JSONB, + main_link_staff TEXT, + contraindications JSONB, + hide_picture INTEGER, + indications JSONB, + link_sale JSONB, + plus_list JSONB, + plus_text TEXT, + plus_title TEXT, + process_text TEXT, + process_title TEXT, + services_list JSONB, + services_photos JSONB, + services_title TEXT, + sort_staff JSONB, + training_text TEXT, + training_text_title TEXT, + why_text TEXT, + why_title TEXT +); + +CREATE TABLE news ( + id INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + name VARCHAR(255), + active BOOLEAN DEFAULT true, + region_id INTEGER, + alias VARCHAR(255), + anons TEXT, + content TEXT, + update_at TIMESTAMP DEFAULT now(), + link_el_price TEXT, + short_name TEXT, + timer TEXT, + timer_bg TEXT, + form_order JSONB, + link_services JSONB, + link_staff JSONB, + photos JSONB +); + +CREATE TABLE promo ( + id INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + name VARCHAR(255), + active BOOLEAN DEFAULT true, + region_id INTEGER, + alias VARCHAR(255), + anons TEXT, + content TEXT, + update_at TIMESTAMP DEFAULT now(), + clinics JSONB, + timer TEXT, + timer_bg TEXT, + short_name TEXT, + link_services JSONB, + link_staff JSONB, + period VARCHAR(255), + photos JSONB +); + +CREATE TABLE site_services ( + id INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + name VARCHAR(255), + active BOOLEAN DEFAULT true, + region_id INTEGER, + alias VARCHAR(255), + anons TEXT, + content TEXT, + update_at TIMESTAMP DEFAULT now(), + link_videoreviews JSONB, + preview_img TEXT, + faq JSONB, + part_price TEXT, + pokazaniya TEXT, + preparation TEXT, + protivopokazaniya TEXT, + hide_sign_btn JSONB, + quiz JSONB, + tags JSONB, + tags_important JSONB, + banner_img TEXT, + banner_img_m TEXT, + banner_img_url TEXT, + clinics JSONB, + download_file TEXT, + full_width_banner TEXT, + staff_up JSONB, + advantages JSONB, + hide_picture INTEGER, + kod_uslug TEXT, + link_price TEXT, + photos_title TEXT, + sale_id JSONB, + sort_staff JSONB, + contraindications_list TEXT, + custom_block_text TEXT, + custom_block_text2 TEXT, + custom_block_title TEXT, + custom_block_title2 TEXT, + indications_list TEXT, + link_articles_services JSONB, + plus_list TEXT, + plus_text TEXT, + plus_title TEXT, + prepare_title TEXT, + process_text TEXT, + process_title TEXT, + services_list TEXT, + services_photos JSONB, + services_title TEXT, + text_up TEXT, + training_text TEXT, + why_text TEXT, + why_title TEXT, + link_faq JSONB, + link_services JSONB, + link_staff JSONB, + photos JSONB +); + +CREATE TABLE web_get_docinfo ( + id INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + source_table VARCHAR(255), + doc_name VARCHAR(255), + doc_post VARCHAR(255), + filial INTEGER, + viewinweb BOOLEAN, + depnum INTEGER, + first_schid INTEGER, + second_schid INTEGER, + accepts_dms BOOLEAN, + anons TEXT, + content TEXT, + updated_at TIMESTAMP DEFAULT now() +); + +CREATE TABLE idoctor ( + id INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + dcode INTEGER, + name VARCHAR(255), + department INTEGER, + filial INTEGER, + nearest_date DATE, + online_mode BOOLEAN DEFAULT true, + updated TIMESTAMP DEFAULT now() +); + diff --git a/data/test/sql/postgres/schema/03-cabinet-schema.sql b/data/test/sql/postgres/schema/03-cabinet-schema.sql new file mode 100644 index 0000000..bb0812a --- /dev/null +++ b/data/test/sql/postgres/schema/03-cabinet-schema.sql @@ -0,0 +1,220 @@ +\connect sova_cabinet_test + +DROP SCHEMA public CASCADE; +CREATE SCHEMA public; +GRANT ALL ON SCHEMA public TO sova_test; + +CREATE TABLE users ( + id INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + email VARCHAR(180), + roles JSONB NOT NULL DEFAULT '[]', + password VARCHAR(255), + uid INTEGER NOT NULL UNIQUE, + token VARCHAR(255), + full_name VARCHAR(255) NOT NULL, + phone VARCHAR(255), + confirm BOOLEAN NOT NULL DEFAULT true, + created_at TIMESTAMP DEFAULT now(), + last_activity_at TIMESTAMP DEFAULT now() +); + +CREATE TABLE city ( + id INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + name VARCHAR(255) NOT NULL, + region_id INTEGER NOT NULL, + time_zone INTEGER NOT NULL DEFAULT 4 +); + +CREATE TABLE filial ( + id INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + fid INTEGER NOT NULL, + name VARCHAR(255) NOT NULL, + address VARCHAR(255) NOT NULL, + address_name VARCHAR(255), + site_id INTEGER, + city_id INTEGER REFERENCES city(id) ON DELETE SET NULL, + active BOOLEAN NOT NULL DEFAULT true, + company VARCHAR(255) +); + +CREATE TABLE banner ( + id INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + href VARCHAR(255) NOT NULL, + src VARCHAR(255) NOT NULL, + active BOOLEAN NOT NULL DEFAULT true, + city_id INTEGER UNIQUE REFERENCES city(id) ON DELETE CASCADE +); + +CREATE TABLE review_source ( + id INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + city_id INTEGER NOT NULL REFERENCES city(id) ON DELETE CASCADE, + name VARCHAR(255) NOT NULL, + count_row INTEGER NOT NULL DEFAULT 0, + active BOOLEAN NOT NULL DEFAULT true, + rating DOUBLE PRECISION NOT NULL DEFAULT 5, + filial_id INTEGER REFERENCES filial(id) ON DELETE SET NULL, + date_create DATE NOT NULL DEFAULT CURRENT_DATE +); + +CREATE TABLE category_page ( + id INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + name VARCHAR(255) NOT NULL, + active BOOLEAN NOT NULL DEFAULT true +); + +CREATE TABLE page ( + id INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + name VARCHAR(255) NOT NULL, + description TEXT NOT NULL, + active BOOLEAN NOT NULL DEFAULT true, + alias VARCHAR(255) NOT NULL, + category_id INTEGER NOT NULL REFERENCES category_page(id) ON DELETE CASCADE +); + +CREATE TABLE department ( + id INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + did INTEGER NOT NULL, + name VARCHAR(255) NOT NULL, + group_name VARCHAR(255) NOT NULL, + online_mode BOOLEAN NOT NULL DEFAULT true, + alias VARCHAR(255) NOT NULL, + active BOOLEAN NOT NULL DEFAULT true, + middle_name VARCHAR(255) +); + +CREATE TABLE price_department ( + id INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + name VARCHAR(255) NOT NULL, + group_id INTEGER NOT NULL, + group_name VARCHAR(255), + doct_count INTEGER DEFAULT 0, + view_in_web BOOLEAN DEFAULT true +); + +CREATE TABLE price_list_view ( + id INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + kodoper INTEGER, + schname VARCHAR(255), + specname VARCHAR(255), + speccode INTEGER, + price_info JSONB, + discpercent INTEGER, + discprice NUMERIC(10,2), + structname VARCHAR(255), + fname VARCHAR(255), + filial INTEGER, + comment TEXT, + media_id INTEGER, + date_update TIMESTAMP DEFAULT now(), + group_id INTEGER +); + +CREATE TABLE price ( + id INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + name VARCHAR(255), + value NUMERIC(10,2), + property_value_id INTEGER, + date_update TIMESTAMP DEFAULT now() +); + +CREATE TABLE specialist_view ( + id INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + name VARCHAR(255) NOT NULL, + kinder INTEGER, + speciality VARCHAR(255), + category VARCHAR(255), + experience VARCHAR(255), + description TEXT, + infoclinica BOOLEAN DEFAULT true, + alias VARCHAR(255) NOT NULL, + dcode INTEGER NOT NULL, + s_type INTEGER, + active BOOLEAN DEFAULT true, + region_id INTEGER, + kodoper JSONB, + updated TIMESTAMP DEFAULT now(), + accepts_dms BOOLEAN DEFAULT true, + degree VARCHAR(255) +); + +CREATE TABLE location_view ( + id INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + dcode INTEGER NOT NULL, + department INTEGER NOT NULL, + filial INTEGER NOT NULL, + specialist_id INTEGER NOT NULL, + online_mode BOOLEAN NOT NULL DEFAULT true, + active BOOLEAN NOT NULL DEFAULT true, + nearest_date DATE +); + +CREATE TABLE remote_review ( + id INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + external_id INTEGER, + specialist_id INTEGER, + active BOOLEAN DEFAULT true, + date_create DATE DEFAULT CURRENT_DATE, + message TEXT, + author VARCHAR(255), + rating DOUBLE PRECISION DEFAULT 5, + source VARCHAR(255) +); + +CREATE TABLE record ( + id INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + specialist_id INTEGER NOT NULL, + phone VARCHAR(255) NOT NULL, + create_at TIMESTAMP NOT NULL DEFAULT now(), + hash VARCHAR(255) NOT NULL, + reserve JSONB NOT NULL DEFAULT '{}' +); + +CREATE TABLE alert_sms ( + id INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + record_id INTEGER UNIQUE REFERENCES record(id) ON DELETE CASCADE, + date_create TIMESTAMP NOT NULL DEFAULT now(), + response TEXT NOT NULL +); + +CREATE TABLE widget_form ( + id INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + name VARCHAR(255) NOT NULL +); + +CREATE TABLE widget_form_input ( + id INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + text VARCHAR(255) NOT NULL, + type VARCHAR(255) NOT NULL, + bitrix24_id VARCHAR(255) NOT NULL, + widget_form_id INTEGER REFERENCES widget_form(id) ON DELETE CASCADE, + sort INTEGER NOT NULL DEFAULT 100 +); + +CREATE TABLE usrlog ( + id INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + pcode INTEGER, + agent TEXT, + client_ip VARCHAR(255), + method VARCHAR(255), + created_at TIMESTAMP DEFAULT now() +); + +CREATE TABLE direct_company ( + id INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + name VARCHAR(255), + company_id BIGINT, + city VARCHAR(255) +); + +CREATE TABLE direct_report ( + id INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + date DATE, + ad_group_id BIGINT, + campaign_id BIGINT, + ad_id BIGINT, + impressions INTEGER, + clicks INTEGER, + cost DOUBLE PRECISION, + conversions INTEGER +); + diff --git a/data/test/sql/postgres/seed/01-create-databases.seed.sql b/data/test/sql/postgres/seed/01-create-databases.seed.sql new file mode 100644 index 0000000..e69de29 diff --git a/data/test/sql/postgres/seed/02-backend-seed.sql b/data/test/sql/postgres/seed/02-backend-seed.sql new file mode 100644 index 0000000..10c2c21 --- /dev/null +++ b/data/test/sql/postgres/seed/02-backend-seed.sql @@ -0,0 +1,99 @@ +\connect sova_backend_test + +INSERT INTO users (uid, email, roles, region_id, password, birth_date) +VALUES (100001, '8e6ec50bec697ce8e2663b4790264408', '["ROLE_USER","ROLE_ADMIN"]', 91, '$2y$13$Y98kYF03yQjzDo0HsvvWMu..4SqB3Kgv2d8GNf870MEjJbXUJ2i.a', '1990-01-01'); + +INSERT INTO departments (did, name, online_mode, alias, group_name) +VALUES (10, 'Терапия', true, 'terapiya', 'Взрослые специалисты'); + +INSERT INTO filial (fid, name, address, region_id, site_id, company, short_name, phone, email) +VALUES + (1, 'Сова Саратов', 'Localhost, 1', 91, 1, 'ООО Local Clinic', 'Саратов', '+70000000001', 'saratov@example.test'), + (2, 'Сова Волгоград', 'Localhost, 2', 92, 2, 'ООО Local Clinic', 'Волгоград', '+70000000002', 'volgograd@example.test'), + (3, 'Сова Воронеж', 'Localhost, 3', 93, 3, 'ООО Local Clinic', 'Воронеж', '+70000000003', 'voronezh@example.test'), + (4, 'Сова Краснодар', 'Localhost, 4', 94, 4, 'ООО Local Clinic', 'Краснодар', '+70000000004', 'krasnodar@example.test'); + +INSERT INTO specialist (name, active, display_schedule, dcodes, region_id, alias, post, experience, s_type, anons, content, kodoper, filials, accepts_dms, specialities) +VALUES ('Иванов Иван Иванович', true, true, '101', 91, 'ivanov-ivan', 'Врач-терапевт', '2014', 1, 'Тестовый врач', 'Тестовое описание врача', '[1001]', '[1]', true, '["Терапия"]'); + +INSERT INTO location (dcode, department, filial, online_mode, active, nearest_date, specialist_id) +VALUES (101, 10, 1, true, true, CURRENT_DATE + interval '1 day', 1); + +INSERT INTO review (specialist_id, message, author, rating, source, external_id) +VALUES (1, 'Тестовый отзыв для локальной базы', 'Пациент Local', 5, 'local', 1); + +INSERT INTO specialist_docs (specialist_id, name, active, type) +VALUES (1, 'Тестовый сертификат', true, 'certificate'); + +INSERT INTO specialist_dcode_description (dcode, department, specialist_id, content) +VALUES (101, 10, 1, 'Локальное описание врача по dcode.'); + +INSERT INTO stock (name, content, anons) +VALUES ('Local акция', 'Тестовая акция только для локальной разработки', 'Local'); + +INSERT INTO stock_specialist (stock_id, specialist_id) VALUES (1, 1); + +INSERT INTO price_department (name, group_id, doct_count, view_in_web) +VALUES ('Консультации', 100, 1, true); + +INSERT INTO price_list (kodoper, schname, specname, speccode, price_info, discprice, structname, fname, filial, group_id) +VALUES (1001, 'Прием терапевта', 'Иванов Иван Иванович', 101, '{"base":1500,"discount":1200}', 1200, 'Терапия', 'Сова Local', 1, 100); + +INSERT INTO schedule (dcode, department, filial, schedident, workdate, time, is_free, online_mode, price_info) +VALUES (101, 10, 1, 555001, CURRENT_DATE + interval '1 day', '[{"st":"09:00","en":"09:30"}]', true, true, 1500); + +INSERT INTO record (specialist_id, phone, hash, reserve) +VALUES (1, '+70000000000', 'c2018e2ee0f7d39af2c8f696e7003424', '{"local":true,"date":"tomorrow"}'); + +INSERT INTO alert_sms (record_id, response) +VALUES (1, '{"status":"local-ok"}'); + +INSERT INTO widget_form (name) VALUES ('Local форма'); +INSERT INTO widget_form_input (text, type, bitrix24_id, widget_form_id, sort) +VALUES ('Телефон', 'phone', 'PHONE', 1, 10); + +INSERT INTO article (name, active, region_id, alias, anons, content) +VALUES ('Local статья', true, 91, 'local-article', 'Анонс', 'Контент локальной статьи'); + +INSERT INTO disease (name, active, region_id, alias, anons, content) +VALUES ('Local заболевание', true, 91, 'local-disease', 'Анонс', 'Описание'); + +INSERT INTO medical_center (name, active, region_id, alias, anons, content) +VALUES ('Local медцентр', true, 91, 'local-center', 'Анонс', 'Описание'); + +INSERT INTO news (name, active, region_id, alias, anons, content) +VALUES ('Local новость', true, 91, 'local-news', 'Анонс', 'Контент'); + +INSERT INTO promo (name, active, region_id, alias, anons, content, period) +VALUES ('Local промо', true, 91, 'local-promo', 'Анонс', 'Контент', 'Всегда'); + +INSERT INTO site_services (name, active, region_id, alias, anons, content, tags) +VALUES ('Local услуга', true, 91, 'local-service', 'Анонс', 'Контент', '["local"]'); + +INSERT INTO web_get_docinfo (source_table, doc_name, doc_post, filial, viewinweb, depnum, accepts_dms, anons, content) +VALUES ('local', 'Иванов Иван Иванович', 'Врач-терапевт', 1, true, 10, true, 'Анонс', 'Описание'); + +INSERT INTO idoctor (dcode, name, department, filial, nearest_date, online_mode) +VALUES (101, 'Иванов Иван Иванович', 10, 1, CURRENT_DATE + interval '1 day', true); + +-- После seed INSERT sequence identity должен указывать на MAX(id), иначе CREATE вернёт duplicate key id=1. +DO $body$ +DECLARE + tbl text; +BEGIN + FOREACH tbl IN ARRAY ARRAY[ + 'users', 'departments', 'filial', 'specialist', 'location', 'review', + 'specialist_docs', 'specialist_dcode_description', 'stock', + 'price_department', 'price_list', 'schedule', 'record', 'alert_sms', + 'widget_form', 'widget_form_input', 'article', 'disease', 'medical_center', + 'news', 'promo', 'site_services', 'web_get_docinfo', 'idoctor' + ] + LOOP + EXECUTE format( + 'SELECT setval(pg_get_serial_sequence(%L, ''id''), COALESCE((SELECT MAX(id) FROM %I), 1), true)', + tbl, + tbl + ); + END LOOP; +END +$body$; diff --git a/data/test/sql/postgres/seed/03-cabinet-seed.sql b/data/test/sql/postgres/seed/03-cabinet-seed.sql new file mode 100644 index 0000000..7748bb1 --- /dev/null +++ b/data/test/sql/postgres/seed/03-cabinet-seed.sql @@ -0,0 +1,78 @@ +\connect sova_cabinet_test + +INSERT INTO users (email, roles, password, uid, token, full_name, phone, confirm) +VALUES ( + '6c6f63616c2e636162696e6574406578616d706c652e74657374', + '["ROLE_USER","ROLE_ADMIN"]', + '$2y$12$hqHoZsKN01W.IBcfZYRf.OygGbGIMM7RW0M8fZxo.DNjswjj07S2u', + 200001, + 'Yjd4N6Xlvfay4sNPfPf6PBeosTdmpfCl6+xg9a9V7BnHmfocaw6YSD4NF6Vrvqrm9+nwzNsm5KzpoFV23nG8Lw==', + 'qpHB5XVk6VcuthTcmGV7zqBFN805ejONu+ciwz5nwC4AyEjJ0oH7Ci5ISfgpvwbn2NhLHyTA5tCnN2jd4qQogQ==', + '2I/vmVgNZC98ben0LPkqxmZX1oiAP/k+aXCn3+/dxTBCPBlN7VLR9uiSoWcOuxeBi2rAzfl9t1N1b/PJkJO6MQ==', + true +); + +INSERT INTO city (name, region_id, time_zone) +VALUES + ('Саратов Local', 91, 4), + ('Волгоград Local', 92, 3), + ('Воронеж Local', 93, 3), + ('Краснодар Local', 94, 3); + +INSERT INTO filial (fid, name, address, address_name, site_id, city_id, company) +VALUES + (1, 'Сова Саратов', 'Localhost, 1', 'Саратов', 1, 1, 'ООО Local Clinic'), + (2, 'Сова Волгоград', 'Localhost, 2', 'Волгоград', 2, 2, 'ООО Local Clinic'), + (3, 'Сова Воронеж', 'Localhost, 3', 'Воронеж', 3, 3, 'ООО Local Clinic'), + (4, 'Сова Краснодар', 'Localhost, 4', 'Краснодар', 4, 4, 'ООО Local Clinic'); + +INSERT INTO banner (href, src, city_id) +VALUES ('http://localhost:8082', '/banners/local.png', 1); + +INSERT INTO review_source (city_id, name, count_row, rating, filial_id) +VALUES (1, 'Local Reviews', 1, 5, 1); + +INSERT INTO category_page (name, active) VALUES ('Local категория', true); +INSERT INTO page (name, description, active, alias, category_id) +VALUES ('Local страница', 'Контент локальной страницы', true, 'local-page', 1); + +INSERT INTO department (did, name, group_name, online_mode, alias, middle_name) +VALUES (10, 'Терапия', 'Взрослые специалисты', true, 'terapiya', 'терапевта'); + +INSERT INTO price_department (name, group_id, group_name, doct_count, view_in_web) +VALUES ('Консультации', 100, 'Врачи', 1, true); + +INSERT INTO specialist_view (name, kinder, speciality, category, experience, description, alias, dcode, s_type, active, region_id, kodoper, accepts_dms, degree) +VALUES ('Иванов Иван Иванович', 0, 'Терапевт', 'Первая категория', '12', 'Локальный врач', 'ivanov-ivan', 101, 1, true, 91, '[1001]', true, 'к.м.н.'); + +INSERT INTO location_view (dcode, department, filial, specialist_id, online_mode, active, nearest_date) +VALUES (101, 10, 1, 1, true, true, CURRENT_DATE + interval '1 day'); + +INSERT INTO price_list_view (kodoper, schname, specname, speccode, price_info, discpercent, discprice, structname, fname, filial, group_id) +VALUES (1001, 'Прием терапевта', 'Иванов Иван Иванович', 101, '{"base":1500,"discount":1200}', 10, 1200, 'Терапия', 'Сова Local', 1, 100); + +INSERT INTO remote_review (external_id, specialist_id, message, author, rating, source) +VALUES (1, 1, 'Тестовый отзыв для локальной базы', 'Пациент Local', 5, 'local'); + +INSERT INTO record (specialist_id, phone, hash, reserve) +VALUES (1, '+70000000000', 'c2018e2ee0f7d39af2c8f696e7003424', '{"local":true}'); + +INSERT INTO alert_sms (record_id, response) +VALUES (1, '{"status":"local-ok"}'); + +INSERT INTO widget_form (id, name) OVERRIDING SYSTEM VALUE VALUES + (1, 'Local форма'), + (2, 'Вызов врача на дом'); + +INSERT INTO widget_form_input (text, type, bitrix24_id, widget_form_id, sort) VALUES + ('Телефон', 'phone', 'PHONE', 1, 10), + ('ФИО пациента', 'text', 'NAME', 2, 10), + ('Телефон', 'phone', 'PHONE', 2, 20), + ('Адрес выезда', 'text', 'ADDRESS', 2, 30), + ('Комментарий / симптомы', 'textarea', 'COMMENTS', 2, 40); + +SELECT setval(pg_get_serial_sequence('widget_form', 'id'), (SELECT MAX(id) FROM widget_form)); +SELECT setval(pg_get_serial_sequence('widget_form_input', 'id'), (SELECT MAX(id) FROM widget_form_input)); + +INSERT INTO usrlog (pcode, agent, client_ip, method) +VALUES (200001, 'local-agent', '127.0.0.1', 'seed'); diff --git a/data/test/templates/db-init-jobs.yaml b/data/test/templates/db-init-jobs.yaml new file mode 100644 index 0000000..e1abd21 --- /dev/null +++ b/data/test/templates/db-init-jobs.yaml @@ -0,0 +1,132 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: postgres-schema-sql + namespace: {{ .Values.namespace }} +data: +{{- range $path, $_ := .Files.Glob "sql/postgres/schema/*.sql" }} + {{ base $path }}: | +{{ $.Files.Get $path | indent 4 }} +{{- end }} +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: postgres-seed-sql + namespace: {{ .Values.namespace }} +data: +{{- range $path, $_ := .Files.Glob "sql/postgres/seed/*.sql" }} + {{ base $path }}: | +{{ $.Files.Get $path | indent 4 }} +{{- end }} +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: mysql-schema-sql + namespace: {{ .Values.namespace }} +data: +{{- range $path, $_ := .Files.Glob "sql/mysql-bitrix/schema/*.sql" }} + {{ base $path }}: | +{{ $.Files.Get $path | indent 4 }} +{{- end }} +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: mysql-seed-sql + namespace: {{ .Values.namespace }} +data: +{{- range $path, $_ := .Files.Glob "sql/mysql-bitrix/seed/*.sql" }} + {{ base $path }}: | +{{ $.Files.Get $path | indent 4 }} +{{- end }} +--- +apiVersion: batch/v1 +kind: Job +metadata: + name: db-init + namespace: {{ .Values.namespace }} +spec: + backoffLimit: 2 + template: + spec: + restartPolicy: OnFailure + initContainers: + - name: wait-pg + image: postgres:16-alpine + command: + - sh + - -c + - | + until pg_isready -h {{ .Values.postgres.host }} -p 5432 -U {{ .Values.postgres.user }}; do sleep 3; done + - name: wait-mysql + image: mysql:8.0 + env: + - name: MYSQL_PWD + value: {{ .Values.mysql.password | quote }} + command: + - sh + - -c + - | + until mysqladmin ping -h {{ .Values.mysql.host }} -u{{ .Values.mysql.user }} --silent; do sleep 3; done + containers: + - name: init + image: postgres:16-alpine + env: + - name: PGPASSWORD + value: {{ .Values.postgres.password | quote }} + - name: MYSQL_PWD + value: {{ .Values.mysql.password | quote }} + command: + - sh + - -c + - | + set -e + echo "=== Phase 1: schema ===" + for f in $(ls /schema/postgres/*.sql 2>/dev/null | sort); do + [ -s "$f" ] || continue + echo "PG schema: $(basename $f)" + psql -h {{ .Values.postgres.host }} -U {{ .Values.postgres.user }} -d postgres -v ON_ERROR_STOP=1 -f "$f" + done + apk add --no-cache mysql-client >/dev/null + for f in $(ls /schema/mysql/*.sql 2>/dev/null | sort); do + [ -s "$f" ] || continue + echo "MySQL schema: $(basename $f)" + mysql -h {{ .Values.mysql.host }} -u{{ .Values.mysql.user }} {{ .Values.mysql.database }} < "$f" + done + echo "=== Phase 2: seed ===" + for f in $(ls /seed/postgres/*.sql 2>/dev/null | sort); do + [ -s "$f" ] || continue + echo "PG seed: $(basename $f)" + psql -h {{ .Values.postgres.host }} -U {{ .Values.postgres.user }} -d postgres -v ON_ERROR_STOP=1 -f "$f" + done + for f in $(ls /seed/mysql/*.sql 2>/dev/null | sort); do + [ -s "$f" ] || continue + echo "MySQL seed: $(basename $f)" + mysql -h {{ .Values.mysql.host }} -u{{ .Values.mysql.user }} {{ .Values.mysql.database }} < "$f" + done + echo "DB init complete" + volumeMounts: + - name: pg-schema + mountPath: /schema/postgres + - name: mysql-schema + mountPath: /schema/mysql + - name: pg-seed + mountPath: /seed/postgres + - name: mysql-seed + mountPath: /seed/mysql + volumes: + - name: pg-schema + configMap: + name: postgres-schema-sql + - name: mysql-schema + configMap: + name: mysql-schema-sql + - name: pg-seed + configMap: + name: postgres-seed-sql + - name: mysql-seed + configMap: + name: mysql-seed-sql + diff --git a/data/test/templates/namespace.yaml b/data/test/templates/namespace.yaml new file mode 100644 index 0000000..77db5f9 --- /dev/null +++ b/data/test/templates/namespace.yaml @@ -0,0 +1,4 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: {{ .Values.namespace }} diff --git a/data/test/values.yaml b/data/test/values.yaml new file mode 100644 index 0000000..33f996e --- /dev/null +++ b/data/test/values.yaml @@ -0,0 +1,55 @@ +namespace: sova-data-test + +postgresql: + enabled: true + fullnameOverride: postgresql-test + auth: + username: sova_test + password: sova_test_pass + database: sova_backend_test + primary: + persistence: + enabled: true + size: 2Gi + resources: + requests: + memory: 256Mi + limits: + memory: 512Mi + initdb: + scripts: + 01-create-databases.sql: | + CREATE DATABASE sova_cabinet_test; + GRANT ALL PRIVILEGES ON DATABASE sova_cabinet_test TO sova_test; + +mysql: + enabled: true + fullnameOverride: mysql-bitrix-test + auth: + rootPassword: bitrix_root_test + username: bitrix_test + password: bitrix_test_pass + database: sova_bitrix_test + primary: + persistence: + enabled: true + size: 2Gi + resources: + requests: + memory: 256Mi + limits: + memory: 512Mi + +redis: + enabled: true + fullnameOverride: redis-test + auth: + password: redis_test_pass + master: + persistence: + enabled: false + resources: + requests: + memory: 64Mi + limits: + memory: 128Mi