Compare commits
42 Commits
back-offic
...
ab1732d74b
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ab1732d74b | ||
|
|
7df15a4243 | ||
|
|
abb74390e8 | ||
|
|
06a7568386 | ||
|
|
77737f0ba9 | ||
|
|
6de461473e | ||
|
|
db781fd871 | ||
|
|
ce301e9c70 | ||
|
|
64288b5ce1 | ||
|
|
a8bb725f78 | ||
|
|
df2208ab53 | ||
|
|
72deb8d5e3 | ||
|
|
5566e011b7 | ||
|
|
ee23fd2d3c | ||
|
|
2a41062769 | ||
|
|
6624de7a32 | ||
|
|
44553f5bd4 | ||
|
|
5ed255dddb | ||
|
|
650bf137f2 | ||
|
|
3a8bc2f893 | ||
|
|
d29de100c6 | ||
|
|
97214c3a90 | ||
|
|
0b3b2ee463 | ||
|
|
c3e4e695eb | ||
|
|
c112aded47 | ||
|
|
75f029b872 | ||
|
|
f823df7e15 | ||
|
|
af78c053ba | ||
|
|
4ef4223367 | ||
|
|
7b18376d28 | ||
|
|
c64b9cfee8 | ||
|
|
712281d2e8 | ||
|
|
0626dcbe46 | ||
|
|
d288a5fb3c | ||
|
|
75b45abe4f | ||
|
|
2bd98b29eb | ||
|
|
82cbf07120 | ||
|
|
e07356a700 | ||
|
|
5068a3a114 | ||
|
|
333ea45c38 | ||
|
|
b22390f3eb | ||
|
|
3f285ca15f |
2
.gitignore
vendored
2
.gitignore
vendored
@@ -38,7 +38,7 @@ yarn-error.log
|
||||
/libpeerconnection.log
|
||||
testem.log
|
||||
/typings
|
||||
|
||||
/public/images/
|
||||
# System files
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
|
||||
26
angular.json
26
angular.json
@@ -154,7 +154,7 @@
|
||||
},
|
||||
"serve": {
|
||||
"options": {
|
||||
"allowedHosts": ["novo.market", "dexarmarket.ru", "localhost"],
|
||||
"allowedHosts": ["novo.market", "dexarmarket.ru", "dexar.market","localhost"],
|
||||
"proxyConfig": "proxy.conf.json"
|
||||
},
|
||||
"builder": "@angular/build:dev-server",
|
||||
@@ -166,7 +166,8 @@
|
||||
"buildTarget": "Dexarmarket:build:development"
|
||||
},
|
||||
"novo": {
|
||||
"buildTarget": "Dexarmarket:build:novo"
|
||||
"buildTarget": "Dexarmarket:build:novo",
|
||||
"proxyConfig": "proxy.conf.novo.json"
|
||||
},
|
||||
"novo-production": {
|
||||
"buildTarget": "Dexarmarket:build:novo-production"
|
||||
@@ -176,28 +177,9 @@
|
||||
},
|
||||
"extract-i18n": {
|
||||
"builder": "@angular/build:extract-i18n"
|
||||
},
|
||||
"test": {
|
||||
"builder": "@angular/build:karma",
|
||||
"options": {
|
||||
"polyfills": [
|
||||
"zone.js",
|
||||
"zone.js/testing"
|
||||
],
|
||||
"tsConfig": "tsconfig.spec.json",
|
||||
"inlineStyleLanguage": "scss",
|
||||
"assets": [
|
||||
{
|
||||
"glob": "**/*",
|
||||
"input": "public"
|
||||
}
|
||||
],
|
||||
"styles": [
|
||||
"src/styles.scss"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
824
docs/BACKEND_AUTH_INTEGRATION.md
Normal file
824
docs/BACKEND_AUTH_INTEGRATION.md
Normal file
@@ -0,0 +1,824 @@
|
||||
# Авторизация через Telegram — Backend & Bot
|
||||
|
||||
> Всё что нужно Go-разработчику для реализации авторизации.
|
||||
> Фронтенд **полностью готов** и ждёт эти эндпоинты.
|
||||
|
||||
---
|
||||
|
||||
## Статус
|
||||
|
||||
| Компонент | Готов? |
|
||||
|-----------|--------|
|
||||
| Frontend (Angular) — диалог, QR, поллинг, корзина | ✅ Готов |
|
||||
| Telegram бот (обработка `/start`) | ❌ Нужно |
|
||||
| Backend — 6 HTTP-эндпоинтов | ❌ Нужно |
|
||||
| Хранилище сессий + QR-токенов | ❌ Нужно |
|
||||
| CORS для cookie-based запросов | ❌ Нужно |
|
||||
|
||||
---
|
||||
|
||||
## Архитектура
|
||||
|
||||
Два сценария авторизации:
|
||||
|
||||
### Сценарий 1: Прямой вход (кнопка "Войти через Telegram")
|
||||
|
||||
Пользователь нажимает кнопку → открывается Telegram → бот выдаёт кнопку "Войти на сайт" → callback ставит cookie → фронтенд поллит `/auth/session`.
|
||||
|
||||
### Сценарий 2: QR-логин с десктопа (основной)
|
||||
|
||||
```
|
||||
ДЕСКТОП БРАУЗЕР СЕРВЕР (Go) TELEGRAM
|
||||
│ │ │
|
||||
│ 1. POST /auth/qr/create │ │
|
||||
│ ─────────────────────────────> │ │
|
||||
│ { token: "abc", url: "..." } │ │
|
||||
│ <───────────────────────────── │ │
|
||||
│ │ │
|
||||
│ 2. Показать QR: │ │
|
||||
│ t.me/Bot?start=login_abc │ │
|
||||
│ │ │
|
||||
│ ПОЛЬЗОВАТЕЛЬ СКАНИРУЕТ ТЕЛЕФОНОМ │
|
||||
│ │ │
|
||||
│ │ 3. /start login_abc │
|
||||
│ │ <────────────────────────│
|
||||
│ │ │
|
||||
│ │ Бот → POST /auth/qr/confirm
|
||||
│ │ Бот → "✅ Вы вошли!" │
|
||||
│ │ ────────────────────────>│
|
||||
│ │ │
|
||||
│ 4. GET /auth/qr/poll?token=abc │ │
|
||||
│ (каждые 3 сек) │ │
|
||||
│ ─────────────────────────────> │ │
|
||||
│ { status: "confirmed", │ │
|
||||
│ session: {...} } │ │
|
||||
│ + Set-Cookie: dx_session=... │ │
|
||||
│ <───────────────────────────── │ │
|
||||
│ │ │
|
||||
│ 5. POST /websession/{sessionId} │ │
|
||||
│ [{ itemID, quantity, ... }] │ ← корзина │
|
||||
│ ─────────────────────────────> │ │
|
||||
│ │ │
|
||||
│ 6. Готово! Авторизован + корзина│ │
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Бренды и боты
|
||||
|
||||
| Бренд | Username бота | Домен фронтенда | API сервер | Cookie Domain |
|
||||
|-------|---------------|------------------|------------|---------------|
|
||||
| Dexar | `DexarSupport_bot` | `dexarmarket.ru` | `api.dexarmarket.ru:445` | `.dexarmarket.ru` |
|
||||
| Novo | `novomarket_bot` | `novo.market` | `api.novo.market:444` | `.novo.market` |
|
||||
|
||||
Бот создаётся через https://t.me/BotFather → `/newbot`. Сохранить `BOT_TOKEN`.
|
||||
|
||||
---
|
||||
|
||||
## Хранилище
|
||||
|
||||
### Структура: Сессия
|
||||
|
||||
```go
|
||||
type Session struct {
|
||||
SessionID string `json:"sessionId"`
|
||||
TelegramUserID int64 `json:"telegramUserId"`
|
||||
Username *string `json:"username"` // может быть null
|
||||
DisplayName string `json:"displayName"`
|
||||
Active bool `json:"active"`
|
||||
ExpiresAt time.Time `json:"expiresAt"`
|
||||
}
|
||||
```
|
||||
|
||||
**TTL:** 24 часа.
|
||||
|
||||
### Структура: QR-токен (одноразовый)
|
||||
|
||||
```go
|
||||
type AuthToken struct {
|
||||
Token string `json:"token"`
|
||||
Status string `json:"status"` // "pending" | "confirmed" | "expired"
|
||||
SessionID string `json:"sessionId"` // заполняется после подтверждения ботом
|
||||
CreatedAt time.Time `json:"createdAt"`
|
||||
ExpiresAt time.Time `json:"expiresAt"`
|
||||
}
|
||||
```
|
||||
|
||||
**TTL:** 5 минут.
|
||||
|
||||
### Варианты хранения
|
||||
|
||||
**Redis (рекомендуется):**
|
||||
```go
|
||||
// Сессия
|
||||
redisClient.Set(ctx, "session:"+s.SessionID, json, 24*time.Hour)
|
||||
|
||||
// QR-токен
|
||||
redisClient.Set(ctx, "auth_token:"+t.Token, json, 5*time.Minute)
|
||||
```
|
||||
|
||||
**sync.Map (для MVP):**
|
||||
```go
|
||||
var sessions sync.Map
|
||||
var authTokens sync.Map
|
||||
|
||||
// Очистка устаревших токенов — запустить горутину при старте
|
||||
func cleanupExpiredTokens() {
|
||||
ticker := time.NewTicker(1 * time.Minute)
|
||||
for range ticker.C {
|
||||
authTokens.Range(func(key, value any) bool {
|
||||
t := value.(AuthToken)
|
||||
if time.Now().After(t.ExpiresAt) {
|
||||
authTokens.Delete(key)
|
||||
}
|
||||
return true
|
||||
})
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## HTTP-эндпоинты
|
||||
|
||||
### 1. `POST /auth/qr/create`
|
||||
|
||||
Фронтенд вызывает при открытии диалога логина. Создаёт одноразовый QR-токен.
|
||||
|
||||
```go
|
||||
func handleQrCreate(w http.ResponseWriter, r *http.Request) {
|
||||
// 1. Сгенерировать криптографически безопасный токен
|
||||
tokenBytes := make([]byte, 32)
|
||||
if _, err := rand.Read(tokenBytes); err != nil {
|
||||
http.Error(w, "internal error", 500)
|
||||
return
|
||||
}
|
||||
token := base64.URLEncoding.WithPadding(base64.NoPadding).EncodeToString(tokenBytes)
|
||||
|
||||
// 2. Определить бота по origin
|
||||
botUsername := getBotForOrigin(r.Header.Get("Origin"))
|
||||
|
||||
// 3. Сохранить токен
|
||||
authToken := AuthToken{
|
||||
Token: token,
|
||||
Status: "pending",
|
||||
CreatedAt: time.Now(),
|
||||
ExpiresAt: time.Now().Add(5 * time.Minute),
|
||||
}
|
||||
saveAuthToken(authToken)
|
||||
|
||||
// 4. Ответить
|
||||
qrURL := fmt.Sprintf("https://t.me/%s?start=login_%s", botUsername, token)
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
json.NewEncoder(w).Encode(map[string]string{
|
||||
"token": token,
|
||||
"url": qrURL,
|
||||
})
|
||||
}
|
||||
|
||||
func getBotForOrigin(origin string) string {
|
||||
if strings.Contains(origin, "novo.market") {
|
||||
return "novomarket_bot"
|
||||
}
|
||||
return "DexarSupport_bot"
|
||||
}
|
||||
```
|
||||
|
||||
**Ответ:**
|
||||
```json
|
||||
{ "token": "dG9rZW4tYWJj....", "url": "https://t.me/DexarSupport_bot?start=login_dG9rZW4tYWJj...." }
|
||||
```
|
||||
|
||||
> Telegram ограничивает `start` до 64 символов. `login_` (6) + base64url из 32 байт (43) = 49 ✅
|
||||
|
||||
---
|
||||
|
||||
### 2. `GET /auth/qr/poll?token={token}`
|
||||
|
||||
Фронтенд вызывает каждые 3 секунды. Когда бот подтвердил — возвращает сессию и ставит cookie.
|
||||
|
||||
```go
|
||||
func handleQrPoll(w http.ResponseWriter, r *http.Request) {
|
||||
tokenStr := r.URL.Query().Get("token")
|
||||
if tokenStr == "" {
|
||||
http.Error(w, "missing token", 400)
|
||||
return
|
||||
}
|
||||
|
||||
authToken, ok := getAuthToken(tokenStr)
|
||||
if !ok {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
json.NewEncoder(w).Encode(map[string]string{"status": "expired"})
|
||||
return
|
||||
}
|
||||
|
||||
switch authToken.Status {
|
||||
case "pending":
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
json.NewEncoder(w).Encode(map[string]string{"status": "pending"})
|
||||
|
||||
case "confirmed":
|
||||
session, err := getSession(authToken.SessionID)
|
||||
if err != nil {
|
||||
http.Error(w, "session not found", 500)
|
||||
return
|
||||
}
|
||||
|
||||
// Cookie в ДЕСКТОПНЫЙ браузер
|
||||
domain := getDomainForOrigin(r.Header.Get("Origin"))
|
||||
http.SetCookie(w, &http.Cookie{
|
||||
Name: "dx_session",
|
||||
Value: session.SessionID,
|
||||
Path: "/",
|
||||
HttpOnly: true,
|
||||
Secure: true,
|
||||
SameSite: http.SameSiteNoneMode,
|
||||
MaxAge: 86400,
|
||||
Domain: domain,
|
||||
})
|
||||
|
||||
// Удалить использованный токен
|
||||
deleteAuthToken(tokenStr)
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
json.NewEncoder(w).Encode(map[string]interface{}{
|
||||
"status": "confirmed",
|
||||
"session": session,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func getDomainForOrigin(origin string) string {
|
||||
if strings.Contains(origin, "novo.market") {
|
||||
return ".novo.market"
|
||||
}
|
||||
return ".dexarmarket.ru"
|
||||
}
|
||||
```
|
||||
|
||||
**Ответы:**
|
||||
|
||||
| Статус | JSON |
|
||||
|--------|------|
|
||||
| Ждём | `{ "status": "pending" }` |
|
||||
| Подтверждено | `{ "status": "confirmed", "session": { sessionId, telegramUserId, username, displayName, active, expiresAt } }` + `Set-Cookie` |
|
||||
| Истекло | `{ "status": "expired" }` |
|
||||
|
||||
---
|
||||
|
||||
### 3. `POST /auth/qr/confirm` (внутренний, для бота)
|
||||
|
||||
Бот вызывает когда пользователь отсканировал QR. Привязывает сессию к токену.
|
||||
|
||||
```go
|
||||
func handleQrConfirm(w http.ResponseWriter, r *http.Request) {
|
||||
// Проверить секрет бота
|
||||
if r.Header.Get("X-Bot-Secret") != os.Getenv("BOT_INTERNAL_SECRET") {
|
||||
http.Error(w, "forbidden", 403)
|
||||
return
|
||||
}
|
||||
|
||||
var req struct {
|
||||
Token string `json:"token"`
|
||||
User struct {
|
||||
ID int64 `json:"id"`
|
||||
FirstName string `json:"first_name"`
|
||||
LastName string `json:"last_name"`
|
||||
Username string `json:"username"`
|
||||
} `json:"telegram_user"`
|
||||
}
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
http.Error(w, "bad request", 400)
|
||||
return
|
||||
}
|
||||
|
||||
authToken, ok := getAuthToken(req.Token)
|
||||
if !ok || authToken.Status != "pending" {
|
||||
http.Error(w, "token not found or already used", 404)
|
||||
return
|
||||
}
|
||||
|
||||
// Создать сессию
|
||||
displayName := req.User.FirstName
|
||||
if req.User.LastName != "" {
|
||||
displayName += " " + req.User.LastName
|
||||
}
|
||||
var username *string
|
||||
if req.User.Username != "" {
|
||||
username = &req.User.Username
|
||||
}
|
||||
|
||||
session := Session{
|
||||
SessionID: uuid.New().String(),
|
||||
TelegramUserID: req.User.ID,
|
||||
Username: username,
|
||||
DisplayName: displayName,
|
||||
Active: true,
|
||||
ExpiresAt: time.Now().Add(24 * time.Hour),
|
||||
}
|
||||
saveSession(session)
|
||||
|
||||
// Привязать сессию к токену
|
||||
authToken.Status = "confirmed"
|
||||
authToken.SessionID = session.SessionID
|
||||
saveAuthToken(*authToken)
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
json.NewEncoder(w).Encode(map[string]string{"status": "ok"})
|
||||
}
|
||||
```
|
||||
|
||||
**Запрос от бота:**
|
||||
```json
|
||||
{
|
||||
"token": "dG9rZW4tYWJj...",
|
||||
"telegram_user": {
|
||||
"id": 123456789,
|
||||
"first_name": "Иван",
|
||||
"last_name": "Петров",
|
||||
"username": "ivan_petrov"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 4. `GET /auth/session`
|
||||
|
||||
Фронтенд вызывает для проверки текущей сессии. Читает cookie.
|
||||
|
||||
```go
|
||||
func handleGetSession(w http.ResponseWriter, r *http.Request) {
|
||||
cookie, err := r.Cookie("dx_session")
|
||||
if err != nil {
|
||||
http.Error(w, "unauthorized", 401)
|
||||
return
|
||||
}
|
||||
|
||||
session, err := getSession(cookie.Value)
|
||||
if err != nil {
|
||||
http.Error(w, "unauthorized", 401)
|
||||
return
|
||||
}
|
||||
|
||||
if time.Now().After(session.ExpiresAt) {
|
||||
session.Active = false
|
||||
saveSession(session)
|
||||
}
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
json.NewEncoder(w).Encode(session)
|
||||
}
|
||||
```
|
||||
|
||||
**Формат ответа (200)** — фронтенд ожидает **точно эти поля**:
|
||||
|
||||
```json
|
||||
{
|
||||
"sessionId": "550e8400-e29b-41d4-a716-446655440000",
|
||||
"telegramUserId": 123456789,
|
||||
"username": "ivan_petrov",
|
||||
"displayName": "Иван Петров",
|
||||
"active": true,
|
||||
"expiresAt": "2026-03-25T14:30:00Z"
|
||||
}
|
||||
```
|
||||
|
||||
| Поле | Тип | Обязательно | Примечание |
|
||||
|------|-----|-------------|------------|
|
||||
| `sessionId` | string (UUID) | да | Используется для `/websession/{sessionId}` |
|
||||
| `telegramUserId` | number | да | Telegram user ID |
|
||||
| `username` | string / null | нет | Telegram @username |
|
||||
| `displayName` | string | да | "Имя Фамилия" — показывается в UI |
|
||||
| `active` | boolean | да | `false` = истекла |
|
||||
| `expiresAt` | string (ISO 8601) | да | Фронтенд перепроверяет за 60 сек до |
|
||||
|
||||
**Ошибка:** любой HTTP не-200 → фронтенд считает "не авторизован".
|
||||
|
||||
---
|
||||
|
||||
### 5. `GET /auth/telegram/callback`
|
||||
|
||||
Для прямого входа (по кнопке в Telegram, не через QR). Открывается в браузере.
|
||||
|
||||
```go
|
||||
func handleTelegramCallback(w http.ResponseWriter, r *http.Request) {
|
||||
token := r.URL.Query().Get("token")
|
||||
if token == "" {
|
||||
http.Error(w, "missing token", 400)
|
||||
return
|
||||
}
|
||||
|
||||
session, err := getSession(token)
|
||||
if err != nil || !session.Active {
|
||||
http.Error(w, "invalid or expired token", 401)
|
||||
return
|
||||
}
|
||||
|
||||
domain := getDomainForOrigin(r.Header.Get("Origin"))
|
||||
if domain == "" {
|
||||
domain = ".dexarmarket.ru" // fallback для прямого перехода
|
||||
}
|
||||
|
||||
http.SetCookie(w, &http.Cookie{
|
||||
Name: "dx_session",
|
||||
Value: session.SessionID,
|
||||
Path: "/",
|
||||
HttpOnly: true,
|
||||
Secure: true,
|
||||
SameSite: http.SameSiteNoneMode,
|
||||
MaxAge: 86400,
|
||||
Domain: domain,
|
||||
})
|
||||
|
||||
// Редирект на сайт
|
||||
http.Redirect(w, r, "https://dexarmarket.ru", http.StatusFound)
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 6. `POST /auth/logout`
|
||||
|
||||
```go
|
||||
func handleLogout(w http.ResponseWriter, r *http.Request) {
|
||||
cookie, err := r.Cookie("dx_session")
|
||||
if err == nil {
|
||||
deleteSession(cookie.Value)
|
||||
}
|
||||
|
||||
http.SetCookie(w, &http.Cookie{
|
||||
Name: "dx_session",
|
||||
Value: "",
|
||||
Path: "/",
|
||||
HttpOnly: true,
|
||||
Secure: true,
|
||||
SameSite: http.SameSiteNoneMode,
|
||||
MaxAge: -1,
|
||||
Domain: ".dexarmarket.ru",
|
||||
})
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.Write([]byte(`{"message":"ok"}`))
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Cookie-параметры
|
||||
|
||||
| Параметр | Значение | Почему |
|
||||
|----------|----------|--------|
|
||||
| `Name` | `dx_session` | |
|
||||
| `SameSite` | `None` | Фронтенд на `dexarmarket.ru`, API на `api.dexarmarket.ru:445` — разные origins |
|
||||
| `Secure` | `true` | Обязательно при `SameSite=None` |
|
||||
| `Domain` | `.dexarmarket.ru` | Доступна и на `dexarmarket.ru` и на `api.dexarmarket.ru` |
|
||||
| `HttpOnly` | `true` | Недоступна из JS — защита от XSS |
|
||||
| `MaxAge` | `86400` | 24 часа |
|
||||
|
||||
---
|
||||
|
||||
## CORS
|
||||
|
||||
Фронтенд шлёт `withCredentials: true`. Бэкенд обязан вернуть правильные заголовки.
|
||||
|
||||
```go
|
||||
func corsMiddleware(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
origin := r.Header.Get("Origin")
|
||||
|
||||
allowed := map[string]bool{
|
||||
"https://dexarmarket.ru": true,
|
||||
"https://www.dexarmarket.ru": true,
|
||||
"https://novo.market": true,
|
||||
"https://www.novo.market": true,
|
||||
"http://localhost:4200": true,
|
||||
}
|
||||
|
||||
if allowed[origin] {
|
||||
w.Header().Set("Access-Control-Allow-Origin", origin) // НЕ "*"
|
||||
w.Header().Set("Access-Control-Allow-Credentials", "true")
|
||||
w.Header().Set("Access-Control-Allow-Methods", "GET, POST, OPTIONS")
|
||||
w.Header().Set("Access-Control-Allow-Headers", "Content-Type")
|
||||
}
|
||||
|
||||
if r.Method == "OPTIONS" {
|
||||
w.WriteHeader(200)
|
||||
return
|
||||
}
|
||||
|
||||
next.ServeHTTP(w, r)
|
||||
})
|
||||
}
|
||||
```
|
||||
|
||||
> **Критично:** `Access-Control-Allow-Origin` не может быть `"*"` при `withCredentials`. Вернуть конкретный origin.
|
||||
|
||||
---
|
||||
|
||||
## Роутинг
|
||||
|
||||
```go
|
||||
mux := http.NewServeMux()
|
||||
|
||||
// Существующие
|
||||
mux.HandleFunc("GET /items/{id}", handleGetItem)
|
||||
mux.HandleFunc("GET /category", handleGetCategories)
|
||||
mux.HandleFunc("POST /websession/{id}", handleWebSession)
|
||||
mux.HandleFunc("POST /websession/{id}/qr", handleCreateQR)
|
||||
mux.HandleFunc("GET /websession/{id}/{qrId}", handleCheckPayment)
|
||||
|
||||
// Auth — прямой вход
|
||||
mux.HandleFunc("GET /auth/session", handleGetSession)
|
||||
mux.HandleFunc("GET /auth/telegram/callback", handleTelegramCallback)
|
||||
mux.HandleFunc("POST /auth/logout", handleLogout)
|
||||
|
||||
// Auth — QR-логин
|
||||
mux.HandleFunc("POST /auth/qr/create", handleQrCreate)
|
||||
mux.HandleFunc("GET /auth/qr/poll", handleQrPoll)
|
||||
mux.HandleFunc("POST /auth/qr/confirm", handleQrConfirm)
|
||||
|
||||
handler := corsMiddleware(mux)
|
||||
http.ListenAndServeTLS(":445", "cert.pem", "key.pem", handler)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Telegram-бот
|
||||
|
||||
### Обработчик `/start`
|
||||
|
||||
```go
|
||||
const (
|
||||
confirmURL = "http://localhost:8080/auth/qr/confirm"
|
||||
botInternalSecret = os.Getenv("BOT_INTERNAL_SECRET")
|
||||
)
|
||||
|
||||
func handleStart(update tgbotapi.Update) {
|
||||
text := update.Message.Text
|
||||
user := update.Message.From
|
||||
|
||||
switch {
|
||||
case strings.HasPrefix(text, "/start login_"):
|
||||
handleQrLogin(update, user, strings.TrimPrefix(text, "/start login_"))
|
||||
|
||||
case strings.HasPrefix(text, "/start auth"):
|
||||
handleDirectAuth(update, user)
|
||||
|
||||
default:
|
||||
sendWelcome(update)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### QR-логин (основной)
|
||||
|
||||
```go
|
||||
func handleQrLogin(update tgbotapi.Update, user *tgbotapi.User, token string) {
|
||||
reqBody := map[string]interface{}{
|
||||
"token": token,
|
||||
"telegram_user": map[string]interface{}{
|
||||
"id": user.ID,
|
||||
"first_name": user.FirstName,
|
||||
"last_name": user.LastName,
|
||||
"username": user.UserName,
|
||||
},
|
||||
}
|
||||
bodyBytes, _ := json.Marshal(reqBody)
|
||||
|
||||
req, _ := http.NewRequest("POST", confirmURL, bytes.NewReader(bodyBytes))
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
req.Header.Set("X-Bot-Secret", botInternalSecret)
|
||||
|
||||
resp, err := http.DefaultClient.Do(req)
|
||||
if err != nil || resp.StatusCode != 200 {
|
||||
msg := tgbotapi.NewMessage(update.Message.Chat.ID,
|
||||
"❌ Не удалось войти. QR-код мог устареть. Попробуйте обновить страницу и отсканировать новый QR.")
|
||||
bot.Send(msg)
|
||||
return
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
displayName := buildDisplayName(user)
|
||||
msg := tgbotapi.NewMessage(update.Message.Chat.ID,
|
||||
fmt.Sprintf("✅ Вы вошли на сайт как %s!\n\nМожете вернуться в браузер — страница обновится автоматически.", displayName))
|
||||
bot.Send(msg)
|
||||
}
|
||||
|
||||
func buildDisplayName(user *tgbotapi.User) string {
|
||||
name := user.FirstName
|
||||
if user.LastName != "" {
|
||||
name += " " + user.LastName
|
||||
}
|
||||
return name
|
||||
}
|
||||
```
|
||||
|
||||
### Прямой вход (кнопка, для обратной совместимости)
|
||||
|
||||
```go
|
||||
func handleDirectAuth(update tgbotapi.Update, user *tgbotapi.User) {
|
||||
session := Session{
|
||||
SessionID: uuid.New().String(),
|
||||
TelegramUserID: user.ID,
|
||||
Username: stringPtr(user.UserName),
|
||||
DisplayName: buildDisplayName(user),
|
||||
Active: true,
|
||||
ExpiresAt: time.Now().Add(24 * time.Hour),
|
||||
}
|
||||
saveSession(session)
|
||||
|
||||
callbackURL := "https://api.dexarmarket.ru:445/auth/telegram/callback"
|
||||
loginURL := callbackURL + "?token=" + session.SessionID
|
||||
|
||||
msg := tgbotapi.NewMessage(update.Message.Chat.ID, "Нажмите кнопку чтобы войти:")
|
||||
msg.ReplyMarkup = tgbotapi.NewInlineKeyboardMarkup(
|
||||
tgbotapi.NewInlineKeyboardRow(
|
||||
tgbotapi.NewInlineKeyboardButtonURL("🔐 Войти на сайт", loginURL),
|
||||
),
|
||||
)
|
||||
bot.Send(msg)
|
||||
}
|
||||
```
|
||||
|
||||
### Запуск бота (long polling)
|
||||
|
||||
```go
|
||||
func main() {
|
||||
bot, _ := tgbotapi.NewBotAPI(os.Getenv("BOT_TOKEN"))
|
||||
|
||||
u := tgbotapi.NewUpdate(0)
|
||||
u.Timeout = 60
|
||||
updates := bot.GetUpdatesChan(u)
|
||||
|
||||
for update := range updates {
|
||||
if update.Message != nil && strings.HasPrefix(update.Message.Text, "/start") {
|
||||
handleStart(update)
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Синхронизация корзины
|
||||
|
||||
Сразу после QR-логина фронтенд автоматически отправляет корзину:
|
||||
|
||||
```
|
||||
POST /websession/{sessionId}
|
||||
```
|
||||
|
||||
Тело — массив:
|
||||
```json
|
||||
[
|
||||
{
|
||||
"itemID": 123,
|
||||
"quantity": 2,
|
||||
"colour": "#ff0000",
|
||||
"size": "XL",
|
||||
"price": 1500
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
| Поле | Тип | Примечание |
|
||||
|------|-----|------------|
|
||||
| `itemID` | number | ID товара |
|
||||
| `quantity` | number | Количество |
|
||||
| `colour` | string | CSS hex (`#ff0000`). Бэкенд отдаёт `0xff0000`, фронтенд конвертирует |
|
||||
| `size` | string | `"default"` если размер один |
|
||||
| `price` | number | Финальная цена **с учётом скидки** |
|
||||
|
||||
> Этот эндпоинт (`POST /websession/{id}`) уже существует. Ничего менять не нужно, просто учитывать что он вызывается сразу после успешного логина.
|
||||
|
||||
---
|
||||
|
||||
## Безопасность
|
||||
|
||||
### Криптографический токен
|
||||
```go
|
||||
tokenBytes := make([]byte, 32) // 256 бит
|
||||
crypto/rand.Read(tokenBytes)
|
||||
token := base64.URLEncoding.WithPadding(base64.NoPadding).EncodeToString(tokenBytes)
|
||||
```
|
||||
**НЕ использовать:** `math/rand`, UUID, timestamp.
|
||||
|
||||
### Токен одноразовый
|
||||
- После `confirmed` → удалить при первом успешном `poll`
|
||||
- После 5 минут → автоудаление (TTL)
|
||||
- Повторный `poll` → `"expired"`
|
||||
|
||||
### Защита `/auth/qr/confirm`
|
||||
```go
|
||||
if r.Header.Get("X-Bot-Secret") != os.Getenv("BOT_INTERNAL_SECRET") {
|
||||
http.Error(w, "forbidden", 403)
|
||||
return
|
||||
}
|
||||
```
|
||||
Дополнительно: можно ограничить по IP (`127.0.0.1`) если бот на том же сервере.
|
||||
|
||||
### Rate limiting для `/auth/qr/create`
|
||||
Не более **5 токенов в минуту** с одного IP:
|
||||
```go
|
||||
var ipCounts sync.Map
|
||||
|
||||
func rateLimitQrCreate(ip string) bool {
|
||||
key := ip + ":" + time.Now().Format("2006-01-02T15:04")
|
||||
val, _ := ipCounts.LoadOrStore(key, new(int32))
|
||||
count := atomic.AddInt32(val.(*int32), 1)
|
||||
return count <= 5
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Переменные окружения
|
||||
|
||||
```env
|
||||
BOT_TOKEN=123456:ABC-DEF...
|
||||
BOT_INTERNAL_SECRET=случайная-строка-минимум-32-символа
|
||||
FRONTEND_URL=https://dexarmarket.ru
|
||||
SESSION_TTL=24h
|
||||
REDIS_URL=localhost:6379
|
||||
```
|
||||
|
||||
`BOT_INTERNAL_SECRET` должен совпадать в env сервера и env бота.
|
||||
|
||||
---
|
||||
|
||||
## Тестирование
|
||||
|
||||
### curl-тесты
|
||||
|
||||
**1. Создание токена:**
|
||||
```bash
|
||||
curl -X POST https://api.dexarmarket.ru:445/auth/qr/create \
|
||||
-H "Origin: https://dexarmarket.ru"
|
||||
# → { "token": "dG9r...", "url": "https://t.me/DexarSupport_bot?start=login_dG9r..." }
|
||||
```
|
||||
|
||||
**2. Поллинг (до подтверждения):**
|
||||
```bash
|
||||
curl "https://api.dexarmarket.ru:445/auth/qr/poll?token=dG9r..."
|
||||
# → { "status": "pending" }
|
||||
```
|
||||
|
||||
**3. Подтверждение (имитация бота):**
|
||||
```bash
|
||||
curl -X POST https://api.dexarmarket.ru:445/auth/qr/confirm \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "X-Bot-Secret: ваш-секрет" \
|
||||
-d '{"token":"dG9r...","telegram_user":{"id":123,"first_name":"Тест","last_name":"","username":"testuser"}}'
|
||||
# → { "status": "ok" }
|
||||
```
|
||||
|
||||
**4. Поллинг (после подтверждения):**
|
||||
```bash
|
||||
curl -v "https://api.dexarmarket.ru:445/auth/qr/poll?token=dG9r..."
|
||||
# → { "status": "confirmed", "session": {...} } + Set-Cookie: dx_session=...
|
||||
```
|
||||
|
||||
**5. E2E:**
|
||||
1. Открыть маркетплейс → добавить товар в корзину
|
||||
2. Нажать "Оформить заказ" → появляется диалог с QR
|
||||
3. Отсканировать QR телефоном → Telegram → бот: "✅ Вы вошли!"
|
||||
4. Через 3 сек диалог закрывается → авторизован
|
||||
5. Корзина синхронизирована (`POST /websession/{sessionId}`)
|
||||
|
||||
### Отладка
|
||||
|
||||
| Проблема | Где смотреть |
|
||||
|----------|-------------|
|
||||
| QR не показывается | `POST /auth/qr/create` — ошибка? CORS? |
|
||||
| QR отсканирован, ничего не происходит | Бот получил `/start login_...`? Бот вызвал `confirm`? |
|
||||
| Бот пишет "❌ QR устарел" | Токен expired? 5 минут прошло? |
|
||||
| Поллинг "pending" бесконечно | Бот не вызвал `confirm`. Логи бота |
|
||||
| Поллинг "confirmed" но cookie нет | `SameSite`, `Secure`, `Domain`, CORS |
|
||||
|
||||
---
|
||||
|
||||
## Чеклист
|
||||
|
||||
### Бэкенд (Go)
|
||||
|
||||
- [ ] Структура `Session` + `AuthToken`, функции save/get/delete
|
||||
- [ ] `POST /auth/qr/create` — генерация токена
|
||||
- [ ] `GET /auth/qr/poll?token=...` — статус + cookie при confirmed
|
||||
- [ ] `POST /auth/qr/confirm` — приём от бота с `X-Bot-Secret`
|
||||
- [ ] `GET /auth/session` — чтение cookie, JSON сессии
|
||||
- [ ] `GET /auth/telegram/callback?token=...` — cookie + редирект
|
||||
- [ ] `POST /auth/logout` — удаление сессии и cookie
|
||||
- [ ] TTL 5 мин для токенов, 24ч для сессий
|
||||
- [ ] Rate limiting `/auth/qr/create` (5/мин/IP)
|
||||
- [ ] Очистка устаревших токенов
|
||||
- [ ] CORS middleware
|
||||
- [ ] `BOT_INTERNAL_SECRET` в env
|
||||
|
||||
### Telegram бот
|
||||
|
||||
- [ ] Обработка `/start login_{token}` → `POST /auth/qr/confirm`
|
||||
- [ ] Обработка `/start auth` → создание сессии + кнопка "Войти"
|
||||
- [ ] Сообщения: "✅ Вы вошли" / "❌ QR устарел"
|
||||
- [ ] `BOT_INTERNAL_SECRET` в env (совпадает с сервером)
|
||||
- [ ] `BOT_TOKEN` в env
|
||||
@@ -1,11 +1,748 @@
|
||||
bro we need to do changes, that client required
|
||||
1. we need to add location logic
|
||||
1.1 the catalogs will come or for global or for exact region
|
||||
1.2 need to add a place where the user can choose his region like city if choosed moscow the country is set russian
|
||||
1.3 can we try to understand what country is user logged or whach city by global ip and set it?
|
||||
2. we need to add somekind of user login logic
|
||||
2.1 user can add to cart, look the items and etc without logged in, but when he is going to buy/pay ->
|
||||
at first he have to login with telegram, i will send you the bots adress.
|
||||
2.1.1 if is not logged -> will see the QR or link for logging via telegram
|
||||
2.1.2 if logged we need to ping server to check if he is active user. the expiration date (like day or 5 days) we will get from bakcend with session id
|
||||
2.2 and when user is logged, that time he can do a payment
|
||||
General Information
|
||||
Information exchange with the SBP server is realized via RESTful API. All requests to the server must be executed via HTTPS using GET||POST||PUT||DELETE requests to the given ROOT address. Body of requests must be in JSON format. All not public requests must be signed by the client and the public key must be sent to the server for client identification and sign checking.
|
||||
Header:
|
||||
“Authorization”: {JSON WITH KEY AND PARTNERID}
|
||||
“X-Region” : Moscow | Yerevan | ST. Petersburg
|
||||
“X-Language” : RU | AM | EN
|
||||
“WebSessionID” : f02fe5d6-c6ae-4b2e-9b4d-687534e11b01
|
||||
“Currency” :RUB | AMD | USD
|
||||
Root:
|
||||
API.dexarmarket.ru
|
||||
|
||||
|
||||
General Information
|
||||
Check if server is available
|
||||
Get Marketplaces
|
||||
Set Marketplaces
|
||||
Get Item
|
||||
Delete Item
|
||||
New Item
|
||||
New Callback
|
||||
New Question
|
||||
Get random Items
|
||||
Get items in category
|
||||
Get searched items
|
||||
Get Categories
|
||||
Delete Category
|
||||
New Category
|
||||
Create new websession
|
||||
Check websession status
|
||||
Delete websession status
|
||||
Add to cart
|
||||
Create New QR code for cart checkout
|
||||
Check QR code
|
||||
item structure
|
||||
category structure
|
||||
Check if server is available
|
||||
Client needs to periodically check if the server is available by sending “ping” to the client. On error corresponding message must be shown.
|
||||
Protocol: https
|
||||
Type: GET
|
||||
Path: /ping
|
||||
Request Parameters:
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
Response (Error):
|
||||
{
|
||||
"message": "pong",
|
||||
"status": "Wrong Header"
|
||||
}
|
||||
Response (OK):
|
||||
{
|
||||
"message": "pong",
|
||||
"status": "Correct Header"
|
||||
}
|
||||
________________
|
||||
|
||||
|
||||
Get Marketplaces
|
||||
Get Available Marketplaces
|
||||
Protocol: https
|
||||
Type: GET
|
||||
Path: /marketplaces
|
||||
Request Parameters:
|
||||
{
|
||||
}
|
||||
Response !=200(Error):
|
||||
{
|
||||
"error": "wrong header"
|
||||
}
|
||||
Response =200(OK):
|
||||
{
|
||||
[{“brand” : “dexar”,
|
||||
“api”:”dexar.market”,
|
||||
“bot”:”dexarmarket_bot”,
|
||||
“languagies”:[“”am,”ru”,”en”],
|
||||
“regions”:[“Mosocw - Russia”, ”St Petersburg - Russia”, ”Yerevan - Armenia”]
|
||||
“currency”:[“RUB, ”AMD”, ”USD”]
|
||||
“icon”:”./dexar.market.png”},
|
||||
{“brand” : “store”,
|
||||
“api”:”dexarmarket.store”,
|
||||
“bot”:”dexarstore_bot”,
|
||||
“languagies”:[“”am,”ru”,”en”],
|
||||
“regions”:[“Mosocw - Russia”,”St Petersburg - Russia”,”Yerevan - Armenia”]
|
||||
“currency”:[“”RUB,”AMD”,”USD”]
|
||||
“icon”:”./dexarmarket.store.png”},
|
||||
{“brand” : “Novo”,
|
||||
“api”:”novo.market”,
|
||||
“bot”:”novomarket_bot”,
|
||||
“languagies”:[“”am,”ru”,”en”],
|
||||
“regions”:[“Mosocw - Russia”, ”St Petersburg - Russia”,”Yerevan - Armenia”]
|
||||
“currency”:[“”RUB,”AMD”,”USD”]
|
||||
“icon”:”./novo.market.png”}]
|
||||
|
||||
|
||||
}
|
||||
________________
|
||||
|
||||
|
||||
Set Marketplaces
|
||||
Get Available Marketplaces
|
||||
Protocol: https
|
||||
Type: PUT
|
||||
Path: /marketplaces
|
||||
Request Parameters:
|
||||
{
|
||||
[{“brand” : “dexar”,
|
||||
“api”:”dexar.market”,
|
||||
“languagies”:[“”am,”ru”,”en”],
|
||||
“regions”:[“Mosocw - Russia”,”St Petersburg - Russia”,”Yerevan - Armenia”]
|
||||
“currency”:[“”RUB,”AMD”,”USD”]
|
||||
“icon”:”./dexar.market.png”},
|
||||
{“brand” : “store”,
|
||||
“api”:”dexarmarket.store”,
|
||||
“languagies”:[“”am,”ru”,”en”],
|
||||
“regions”:[“Mosocw - Russia”,”St Petersburg - Russia”,”Yerevan - Armenia”]
|
||||
“currency”:[“”RUB,”AMD”,”USD”]
|
||||
“icon”:”./dexarmarket.store.png”},
|
||||
{“brand” : “Novo”,
|
||||
“api”:”novo.market”,
|
||||
“languagies”:[“”am,”ru”,”en”],
|
||||
“regions”:[“Mosocw - Russia”, ”St Petersburg - Russia”,”Yerevan - Armenia”]
|
||||
“currency”:[“”RUB,”AMD”,”USD”]
|
||||
“icon”:”./novo.market.png”}]
|
||||
|
||||
|
||||
}
|
||||
Response !=200(Error):
|
||||
{
|
||||
"error": "wrong header"
|
||||
}
|
||||
Response =200(OK):
|
||||
{
|
||||
“status”:”Marketplace updated”
|
||||
}
|
||||
________________
|
||||
|
||||
|
||||
Get Item
|
||||
Get Item by ID
|
||||
Protocol: https
|
||||
Type: GET
|
||||
Path: /items/:itemID
|
||||
Request Parameters:
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
Response !=200(Error):
|
||||
{
|
||||
"error": "wrong header"
|
||||
}
|
||||
Response =200(OK):
|
||||
{
|
||||
“itemID”:...
|
||||
}
|
||||
________________
|
||||
Delete Item
|
||||
Delete the item
|
||||
Protocol: https
|
||||
Type: Delete
|
||||
Path: /items/:itemID
|
||||
Request Parameters:
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
Response !=200(Error):
|
||||
{
|
||||
"error": "wrong header"
|
||||
}
|
||||
Response =200(OK):
|
||||
{
|
||||
“status”:”Item was deleted”
|
||||
}
|
||||
________________
|
||||
New Item
|
||||
Create new Item
|
||||
Protocol: https
|
||||
Type: POST
|
||||
Path: /items/:itemID
|
||||
Request Parameters:
|
||||
{
|
||||
“itemID”:...
|
||||
}
|
||||
Response !=200(Error):
|
||||
{
|
||||
"error": "wrong header"
|
||||
}
|
||||
Response =200(OK):
|
||||
{
|
||||
“itemID”:...
|
||||
}
|
||||
________________
|
||||
Update Item
|
||||
Update the item
|
||||
Protocol: https
|
||||
Type: PUT
|
||||
Path: /items/:itemID
|
||||
Request Parameters:
|
||||
{
|
||||
“itemID”:...
|
||||
}
|
||||
Response !=200(Error):
|
||||
{
|
||||
"error": "wrong header"
|
||||
}
|
||||
Response =200(OK):
|
||||
{
|
||||
“status”:”Item updated”
|
||||
}
|
||||
________________
|
||||
|
||||
|
||||
New Callback
|
||||
Update the item
|
||||
Protocol: https
|
||||
Type: POST
|
||||
Path: /items/:itemID/callback
|
||||
Request Parameters:
|
||||
{
|
||||
"rating": 5,
|
||||
"comment": "Отличный товар!",
|
||||
"sessionID": “ f02fe5d6-c6ae-4b2e-9b4d-687534e11b01”
|
||||
"timestamp": "2026-02-28T12:00:00Z"
|
||||
}
|
||||
Response !=200(Error):
|
||||
{
|
||||
"error": "wrong item"
|
||||
}
|
||||
Response =200(OK):
|
||||
{
|
||||
“status”:”Callback added”
|
||||
}
|
||||
________________
|
||||
New Question
|
||||
Update the item
|
||||
Protocol: https
|
||||
Type: POST
|
||||
Path: /items/:itemID/questiion
|
||||
Request Parameters:
|
||||
{
|
||||
"question": "some question!",
|
||||
"sessionID": “ f02fe5d6-c6ae-4b2e-9b4d-687534e11b01”
|
||||
"timestamp": "2026-02-28T12:00:00Z"
|
||||
}
|
||||
Response !=200(Error):
|
||||
{
|
||||
"error": "wrong item"
|
||||
}
|
||||
Response =200(OK):
|
||||
{
|
||||
“status”:”Questiion added”
|
||||
}
|
||||
________________
|
||||
|
||||
|
||||
Get random Items
|
||||
Get given number of items from random categorues
|
||||
Protocol: https
|
||||
Type: GET
|
||||
Path: /items/randomitems?count=15 // 20 is the default
|
||||
Request Parameters:
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
Response !=200(Error):
|
||||
{
|
||||
"error": "wrong header"
|
||||
}
|
||||
Response =200(OK):
|
||||
{
|
||||
[“itemID”:...]
|
||||
}
|
||||
________________
|
||||
Get items in category
|
||||
Get all items in category and in all subcategories inside the category
|
||||
Protocol: https
|
||||
Type: GET
|
||||
Path: /category/:categoryID?count=30, skip=60 // default skip=0, default count=20
|
||||
|
||||
|
||||
Request Parameters:
|
||||
{
|
||||
}
|
||||
Response !=200(Error):
|
||||
{
|
||||
"error": "wrong header"
|
||||
}
|
||||
Response =200(OK):
|
||||
{
|
||||
[“itemID”:...]
|
||||
}
|
||||
________________
|
||||
|
||||
|
||||
Get searched items
|
||||
Get all items in category and in all subcategories inside the category
|
||||
Protocol: https
|
||||
Type: GET
|
||||
Path: /searchitems
|
||||
Parameters:
|
||||
{
|
||||
search (string) — query text
|
||||
categoryIDs (string) — e.g., 1,2,5 (includes all subcategories)
|
||||
minPrice / maxPrice (float) — price range
|
||||
tag (string) — e.g., sale
|
||||
sort (string) — relevance (default), price_asc, price_desc, popular, rating
|
||||
skip / count — default 0 / 20
|
||||
}
|
||||
Examples:
|
||||
* ?search=iphone&sort=popular
|
||||
* ?categoryIDs=1,5&minPrice=100&maxPrice=500
|
||||
* ?tag=new&sort=price_asc&count=10
|
||||
|
||||
|
||||
Request Parameters:
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
Response !=200(Error):
|
||||
{
|
||||
"error": "wrong header"
|
||||
}
|
||||
Response =200(OK):
|
||||
{
|
||||
"total": 12,
|
||||
"skip": 0,
|
||||
"count": 12,
|
||||
"isGlobal": false,
|
||||
"items": [
|
||||
{ "itemID": 101, "name": "..." }
|
||||
]
|
||||
}
|
||||
________________
|
||||
|
||||
|
||||
Get Categories
|
||||
Get all available categories
|
||||
Protocol: https
|
||||
Type: GET
|
||||
Path: /category
|
||||
Request Parameters:
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
Response !=200(Error):
|
||||
{
|
||||
"error": "wrong header"
|
||||
}
|
||||
Response =200(OK):
|
||||
{
|
||||
“categoryID”:...
|
||||
}
|
||||
________________
|
||||
Delete Category
|
||||
Delete EMPTY category, no items and no subcategories must present
|
||||
Protocol: https
|
||||
Type: Delete
|
||||
Path: /category/:categoryID
|
||||
Request Parameters:
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
Response !=200(Error):
|
||||
{
|
||||
"error": "wrong header"
|
||||
}
|
||||
Response =200(OK):
|
||||
{
|
||||
“status”:”Category was deleted”
|
||||
}
|
||||
________________
|
||||
New Category
|
||||
Create new category
|
||||
Protocol: https
|
||||
Type: POST
|
||||
Path: /category/
|
||||
Request Parameters:
|
||||
{
|
||||
“CategoryID”:...
|
||||
}
|
||||
Response !=200(Error):
|
||||
{
|
||||
"error": "wrong header"
|
||||
}
|
||||
Response =200(OK):
|
||||
{
|
||||
“CategoryID”:...
|
||||
}
|
||||
________________
|
||||
Update Category
|
||||
Update existing category
|
||||
Protocol: https
|
||||
Type: PUT
|
||||
Path: /category/:categoryID
|
||||
Request Parameters:
|
||||
{
|
||||
“itemID”:...
|
||||
}
|
||||
Response !=200(Error):
|
||||
{
|
||||
"error": "wrong header"
|
||||
}
|
||||
Response =200(OK):
|
||||
{
|
||||
“status”:”Category was updated”
|
||||
}
|
||||
________________
|
||||
Create new websession
|
||||
Creates a new websession for qr generation. By timeout a new websession must be requested, after the user shows some activity (click on qr).
|
||||
Protocol: https
|
||||
Type POST
|
||||
Path /websession
|
||||
Request Parameters:
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
Response (OK):
|
||||
{
|
||||
"sessionId": “1AF3781BF6B94604B771AEA1D44FA63A”,
|
||||
"userId" : "",
|
||||
"expires" : "sessionId",
|
||||
"userSessionId": "",
|
||||
"status": false
|
||||
}
|
||||
________________
|
||||
Check websession status
|
||||
Check if the user is already logged in. a new websession for qr generation. By timeout a new websession must be requested, after the user shows some activity (click on qr).
|
||||
Protocol: https
|
||||
Type GET
|
||||
Path /websession/:webSessionID
|
||||
Request Parameters:
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
Response (OK):
|
||||
{
|
||||
"sessionId": “1AF3781BF6B94604B771AEA1D44FA63A”,
|
||||
"userId" : "kHaAe9roaC2uq63AKGE/8+Ti/t/iFro68QhEZ1dRGLo",
|
||||
"expires" : "sessionId",
|
||||
"userSessionId": "8A94EFEFD003426A9B456C48CAC99BE6",
|
||||
"x-Region" : "Moscow",
|
||||
"x-Language" : "RU",
|
||||
"currency" : "RUB",
|
||||
"Status": true,
|
||||
"cart": [
|
||||
{ "itemID": 12, "quantity": 1, “colour”:”black”, “size”:”42”,"priice":230.50 },
|
||||
{ "itemID": 13, "quantity": 2, “colour”:”dark”, “size”:”L”,"priice":250.50 },
|
||||
{ "itemID": 14, "quantity": 3, “colour”:”blue”, “size”:”50”,"priice":290.50 },
|
||||
]
|
||||
}
|
||||
________________
|
||||
Delete websession status
|
||||
Delete the session to log out from the system.
|
||||
Protocol: https
|
||||
Type DELETE
|
||||
Path /websession/:webSessionID
|
||||
Request Parameters:
|
||||
{
|
||||
}
|
||||
Response (OK):
|
||||
{
|
||||
“status”:”User logged out”
|
||||
}
|
||||
|
||||
________________
|
||||
Add to cart
|
||||
Add a all item to users (session) cart
|
||||
Protocol: https
|
||||
Type Post
|
||||
Path /websession/:webSessionID
|
||||
Request Parameters:
|
||||
{
|
||||
[
|
||||
{ "itemID": 12, "quantity": 1, “colour”:”black”, “size”:”42”,"priice":230.50 },
|
||||
{ "itemID": 13, "quantity": 2, “colour”:”dark”, “size”:”L”,"priice":250.50 },
|
||||
{ "itemID": 14, "quantity": 3, “colour”:”blue”, “size”:”50”,"priice":290.50 },
|
||||
]
|
||||
}
|
||||
Response (OK):
|
||||
{
|
||||
"sessionId": “1AF3781BF6B94604B771AEA1D44FA63A”,
|
||||
"userId" : "kHaAe9roaC2uq63AKGE/8+Ti/t/iFro68QhEZ1dRGLo",
|
||||
"expires" : "sessionId",
|
||||
"userSessionId": "8A94EFEFD003426A9B456C48CAC99BE6",
|
||||
"Status": true,
|
||||
"cart": [
|
||||
{ "itemID": 12, "quantity": 1, “colour”:”black”, “size”:”42”,"priice":230.50 },
|
||||
{ "itemID": 13, "quantity": 2, “colour”:”dark”, “size”:”L”,"priice":250.50 },
|
||||
{ "itemID": 14, "quantity": 3, “colour”:”blue”, “size”:”50”,"priice":290.50 },
|
||||
]
|
||||
}
|
||||
________________
|
||||
Create New QR code for cart checkout
|
||||
Create New QR for payment via SBP
|
||||
Protocol: https
|
||||
Type POST
|
||||
Path /websession/:webSessionID/qr
|
||||
Request Parameters:
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
Response !=200(Error):
|
||||
{
|
||||
"error": "wrong key"
|
||||
}
|
||||
Response =200(OK):
|
||||
{
|
||||
"qrId": "BD10002CI1V3JP1T8QR8TIQ8K35RBVQB",
|
||||
"qrStatus": "NEW",
|
||||
"qrExpirationDate": "2025-11-20T10:10:44Z",
|
||||
"Payload": "https://qr.nspk.ru/BD10002CI1V3JP1T8QR8TIQ8K35RBVQB?type=02&bank=100000000007&sum=1000&cur=RUB&crc=8ACC",
|
||||
"qrUrl": "https://e-commerce.raiffeisen.ru/api/sbp/v1/qr/BD10002CI1V3JP1T8QR8TIQ8K35RBVQB/image"
|
||||
}
|
||||
________________
|
||||
|
||||
|
||||
Check QR code
|
||||
Check QR status
|
||||
Protocol: https
|
||||
Type GET
|
||||
Path /websession/:webSessionID/:qrID
|
||||
Request Parameters:
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
Response !=200(Error):
|
||||
{
|
||||
"error": "Error from the bank "
|
||||
}
|
||||
Response =200(OK):
|
||||
{
|
||||
"additionalInfo": "",
|
||||
"paymentPurpose": "",
|
||||
"amount": 10,
|
||||
"code": "SUCCESS",
|
||||
"createDate": "2025-11-20T13:17:20.453884+03:00",
|
||||
"currency": "RUB",
|
||||
"order": "102_540",
|
||||
"paymentStatus": "NO_INFO", //check for SUCCESS
|
||||
"qrId": "BD1000263VS7G81D8JCP5FHFTFEH38MT",
|
||||
"transactionDate": "",
|
||||
"transactionId": 0,
|
||||
"qrExpirationDate": "2025-11-20T13:32:20+03:00"
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## 8. Авторизация (вход через Telegram)
|
||||
|
||||
|
||||
Авторизация **через Telegram** с **cookie-сессиями** (HttpOnly, Secure, SameSite=None).
|
||||
|
||||
|
||||
Все auth-эндпоинты должны поддерживать CORS с `credentials: true`.
|
||||
|
||||
|
||||
### Процесс авторизации
|
||||
|
||||
|
||||
```
|
||||
1. Пользователь нажимает «Оформить заказ» → не авторизован → показывается диалог входа
|
||||
2. Нажимает «Войти через Telegram» → открывается https://t.me/{bot}?start=auth_{callback}
|
||||
3. Пользователь запускает бота в Telegram
|
||||
4. Бот отправляет данные пользователя → бэкенд /auth/telegram/callback
|
||||
5. Бэкенд создаёт сессию → устанавливает Set-Cookie
|
||||
6. Фронтенд опрашивает GET /auth/session каждые 3 секунды
|
||||
7. Сессия обнаружена → диалог закрывается → оформление заказа продолжается
|
||||
```
|
||||
|
||||
|
||||
---
|
||||
|
||||
|
||||
### `GET /auth/session` — Проверить текущую сессию
|
||||
|
||||
|
||||
**Запрос:** Только cookie (сессионная cookie, установленная бэкендом).
|
||||
|
||||
|
||||
**Ответ `200`** (авторизован):
|
||||
```json
|
||||
{
|
||||
"sessionId": "sess_abc123",
|
||||
"telegramUserId": 123456789,
|
||||
"username": "john_doe",
|
||||
"displayName": "John Doe",
|
||||
"active": true,
|
||||
"expiresAt": "2026-03-01T12:00:00Z"
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
**Ответ `200`** (сессия истекла):
|
||||
```json
|
||||
{
|
||||
"sessionId": "sess_abc123",
|
||||
"telegramUserId": 123456789,
|
||||
"username": "john_doe",
|
||||
"displayName": "John Doe",
|
||||
"active": false,
|
||||
"expiresAt": "2026-02-27T12:00:00Z"
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
**Ответ `401`** (нет сессии):
|
||||
```json
|
||||
{ "error": "No active session" }
|
||||
```
|
||||
|
||||
|
||||
**Объект AuthSession:**
|
||||
|
||||
|
||||
| Поле | Тип | Обязат. | Описание |
|
||||
|------------------|---------|---------|-------------------------------------------|
|
||||
| `sessionId` | string | да | Уникальный ID сессии |
|
||||
| `telegramUserId` | number | да | ID пользователя в Telegram |
|
||||
| `username` | string? | нет | @username в Telegram (может быть null) |
|
||||
| `displayName` | string | да | Отображаемое имя (имя + фамилия) |
|
||||
| `active` | boolean | да | Действительна ли сессия |
|
||||
| `expiresAt` | string | да | Дата истечения в формате ISO 8601 |
|
||||
|
||||
|
||||
---
|
||||
|
||||
|
||||
### `GET /auth/telegram/callback` — Callback авторизации Telegram-бота
|
||||
|
||||
|
||||
Вызывается Telegram-ботом после авторизации пользователя.
|
||||
|
||||
|
||||
**Тело запроса (от бота):**
|
||||
```json
|
||||
{
|
||||
"id": 123456789,
|
||||
"first_name": "John",
|
||||
"last_name": "Doe",
|
||||
"username": "john_doe",
|
||||
"photo_url": "https://t.me/i/userpic/...",
|
||||
"auth_date": 1709100000,
|
||||
"hash": "abc123def456..."
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
Бот должен:
|
||||
1. Слушать команду `/start auth_{callbackUrl}`
|
||||
2. Извлечь callback URL
|
||||
3. Отправить данные пользователя (`id`, `first_name`, `username` и т.д.) на этот callback URL
|
||||
4. Callback URL: `{apiUrl}/auth/telegram/callback`
|
||||
|
||||
|
||||
---
|
||||
|
||||
|
||||
## Полный справочник эндпоинтов
|
||||
|
||||
|
||||
### Новые эндпоинты
|
||||
|
||||
|
||||
| Метод | Путь | Описание | Авторизация |
|
||||
|--------|---------------------------|---------------------------------|-------------|
|
||||
| `GET` | `/regions` | Список доступных регионов | Нет |
|
||||
| `GET` | `/auth/session` | Проверка текущей сессии | Cookie |
|
||||
| `GET` | `/auth/telegram/callback` | Callback авторизации через бота | Нет (бот) |
|
||||
| `POST` | `/auth/logout` | Завершение сессии | Cookie |
|
||||
|
||||
|
||||
________________
|
||||
|
||||
|
||||
item structure
|
||||
CategoryID uint64 `json:"categoryID" binding:"required"`
|
||||
ItemID uint64 `json:"itemID" binding:"required"`
|
||||
Name string `json:"name" binding:"required"`
|
||||
Description string `json:"description"`
|
||||
Discount float32 `json:"discount" `
|
||||
Rating float32 `json:"rating" binding:"required"`
|
||||
Visible bool `json:"rating"`
|
||||
Priority uint64 `json:"priority"`
|
||||
Tags []string `json:"tags"`
|
||||
Badges []string `json:"badges"`
|
||||
Details []itemdetail `json:"itemdetails"`
|
||||
Colour string `json:"colour" binding:"required"`
|
||||
Size string `json:"size" binding:"required"`
|
||||
Price float32 `json:"price" binding:"required"`
|
||||
Currency string `json:"currency" binding:"required"`
|
||||
Remaining uint64 `json:"remaining" binding:"required"`
|
||||
Names []itemname `json:"names"`
|
||||
Language string `json:"language"`
|
||||
Value string `json:"value"`
|
||||
Descriptions []itemdescription `json:"descriptions" `
|
||||
Language string `json:"language"`
|
||||
Value string `json:"value"`
|
||||
Attributes []attribute `json:"attributes" binding:"required"`
|
||||
Key string `json:"key"`
|
||||
Value string `json:"value"`
|
||||
Photos []photo `json:"photos"`
|
||||
Type string `json:"type" binding:"required"` //video || photo
|
||||
URL string `json:"url" binding:"required"`
|
||||
Questions []question `json:"questions"`
|
||||
Question string `json:"question" `
|
||||
Answer string `json:"answer" `
|
||||
Like uint64 `json:"like" `
|
||||
Dislike uint64 `json:"dislike" `
|
||||
Visits uint64 `json:"visits"`
|
||||
Callbacks []callback `json:"callbacks" binding:"required"`
|
||||
Rating float32 `json:"rating,omitempty"`
|
||||
Content string `json:"content,omitempty"`
|
||||
Userid string `json:"userID"`
|
||||
Answer string `json:"answer"`
|
||||
Timestamp string `json:"timestamp"`
|
||||
PartnerID []string `json:"partnerID" binding:"required"`
|
||||
|
||||
|
||||
category structure
|
||||
CategoryID uint64 `json:"categoryID" binding:"required"`
|
||||
ParentID uint64 `json:"parentID" binding:"required"`
|
||||
Name string `json:"name" binding:"required"`
|
||||
Visible bool `json:"visible" `
|
||||
Priority uint64 `json:"priority" `
|
||||
Icon string `json:"icon"`
|
||||
WideIcon string `json:"wideicon"`
|
||||
ItemsCount uint64
|
||||
CategoriesCount uint64
|
||||
Names []itemname `json:"names"`
|
||||
Language string `json:"language"`
|
||||
Value string `json:"value"`
|
||||
@@ -36,6 +36,9 @@ server {
|
||||
add_header X-Frame-Options "SAMEORIGIN" always;
|
||||
add_header X-Content-Type-Options "nosniff" always;
|
||||
add_header X-XSS-Protection "1; mode=block" always;
|
||||
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
|
||||
add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always;
|
||||
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval' https://telegram.org; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; font-src 'self' https://fonts.gstatic.com; img-src 'self' data: https:; connect-src 'self' https:; frame-src https://telegram.org;" always;
|
||||
|
||||
# Brotli compression (if available)
|
||||
# brotli on;
|
||||
|
||||
@@ -30,7 +30,9 @@
|
||||
{
|
||||
"name": "api-cache",
|
||||
"urls": [
|
||||
"/api/**"
|
||||
"/api/**",
|
||||
"https://api.dexarmarket.ru:445/**",
|
||||
"https://api.novo.market:444/**"
|
||||
],
|
||||
"cacheConfig": {
|
||||
"maxSize": 100,
|
||||
|
||||
1
package-lock.json
generated
1
package-lock.json
generated
@@ -9580,3 +9580,4 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"ng": "ng",
|
||||
"start": "ng serve",
|
||||
"dexar": "ng serve --configuration=development --port 4200",
|
||||
"novo": "ng serve --configuration=novo --port 4201",
|
||||
"novo": "ng serve --configuration=novo --port 4201 --proxy-config proxy.conf.novo.json",
|
||||
"start:dexar": "ng serve --configuration=development --port 4200",
|
||||
"start:novo": "ng serve --configuration=novo --port 4201",
|
||||
"build": "ng build",
|
||||
@@ -47,3 +47,4 @@
|
||||
"typescript": "~5.9.3"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
11
proxy.conf.novo.json
Normal file
11
proxy.conf.novo.json
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"/api": {
|
||||
"target": "https://api.novo.market:444",
|
||||
"secure": false,
|
||||
"changeOrigin": true,
|
||||
"pathRewrite": {
|
||||
"^/api": ""
|
||||
},
|
||||
"logLevel": "debug"
|
||||
}
|
||||
}
|
||||
BIN
public/icons/icon-192x192.png
Normal file
BIN
public/icons/icon-192x192.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 547 B |
BIN
public/icons/icon-512x512.png
Normal file
BIN
public/icons/icon-512x512.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.8 KiB |
@@ -1,5 +1,4 @@
|
||||
{
|
||||
"$schema": "./node_modules/@angular/service-worker/config/schema.json",
|
||||
"name": "Novo Market - Интернет-магазин",
|
||||
"short_name": "Novo",
|
||||
"description": "Novo Market - ваш онлайн магазин качественных товаров с доставкой",
|
||||
@@ -12,34 +11,10 @@
|
||||
"categories": ["shopping", "lifestyle"],
|
||||
"icons": [
|
||||
{
|
||||
"src": "icons/icon-72x72.png",
|
||||
"sizes": "72x72",
|
||||
"type": "image/png",
|
||||
"purpose": "maskable any"
|
||||
},
|
||||
{
|
||||
"src": "icons/icon-96x96.png",
|
||||
"sizes": "96x96",
|
||||
"type": "image/png",
|
||||
"purpose": "maskable any"
|
||||
},
|
||||
{
|
||||
"src": "icons/icon-128x128.png",
|
||||
"sizes": "128x128",
|
||||
"type": "image/png",
|
||||
"purpose": "maskable any"
|
||||
},
|
||||
{
|
||||
"src": "icons/icon-144x144.png",
|
||||
"sizes": "144x144",
|
||||
"type": "image/png",
|
||||
"purpose": "maskable any"
|
||||
},
|
||||
{
|
||||
"src": "icons/icon-152x152.png",
|
||||
"sizes": "152x152",
|
||||
"type": "image/png",
|
||||
"purpose": "maskable any"
|
||||
"src": "assets/images/novo-favicon.svg",
|
||||
"sizes": "any",
|
||||
"type": "image/svg+xml",
|
||||
"purpose": "any"
|
||||
},
|
||||
{
|
||||
"src": "icons/icon-192x192.png",
|
||||
@@ -47,12 +22,6 @@
|
||||
"type": "image/png",
|
||||
"purpose": "maskable any"
|
||||
},
|
||||
{
|
||||
"src": "icons/icon-384x384.png",
|
||||
"sizes": "384x384",
|
||||
"type": "image/png",
|
||||
"purpose": "maskable any"
|
||||
},
|
||||
{
|
||||
"src": "icons/icon-512x512.png",
|
||||
"sizes": "512x512",
|
||||
|
||||
@@ -11,34 +11,10 @@
|
||||
"categories": ["shopping", "marketplace"],
|
||||
"icons": [
|
||||
{
|
||||
"src": "icons/icon-72x72.png",
|
||||
"sizes": "72x72",
|
||||
"type": "image/png",
|
||||
"purpose": "maskable any"
|
||||
},
|
||||
{
|
||||
"src": "icons/icon-96x96.png",
|
||||
"sizes": "96x96",
|
||||
"type": "image/png",
|
||||
"purpose": "maskable any"
|
||||
},
|
||||
{
|
||||
"src": "icons/icon-128x128.png",
|
||||
"sizes": "128x128",
|
||||
"type": "image/png",
|
||||
"purpose": "maskable any"
|
||||
},
|
||||
{
|
||||
"src": "icons/icon-144x144.png",
|
||||
"sizes": "144x144",
|
||||
"type": "image/png",
|
||||
"purpose": "maskable any"
|
||||
},
|
||||
{
|
||||
"src": "icons/icon-152x152.png",
|
||||
"sizes": "152x152",
|
||||
"type": "image/png",
|
||||
"purpose": "maskable any"
|
||||
"src": "assets/images/dexar-favicon.svg",
|
||||
"sizes": "any",
|
||||
"type": "image/svg+xml",
|
||||
"purpose": "any"
|
||||
},
|
||||
{
|
||||
"src": "icons/icon-192x192.png",
|
||||
@@ -46,12 +22,6 @@
|
||||
"type": "image/png",
|
||||
"purpose": "maskable any"
|
||||
},
|
||||
{
|
||||
"src": "icons/icon-384x384.png",
|
||||
"sizes": "384x384",
|
||||
"type": "image/png",
|
||||
"purpose": "maskable any"
|
||||
},
|
||||
{
|
||||
"src": "icons/icon-512x512.png",
|
||||
"sizes": "512x512",
|
||||
|
||||
@@ -12,10 +12,10 @@
|
||||
</div>
|
||||
} @else {
|
||||
<app-header></app-header>
|
||||
@if (!isHomePage()) {
|
||||
<app-back-button />
|
||||
}
|
||||
<main class="main-content">
|
||||
@if (!isHomePage()) {
|
||||
<app-back-button />
|
||||
}
|
||||
<router-outlet></router-outlet>
|
||||
</main>
|
||||
<app-footer></app-footer>
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
import { TestBed } from '@angular/core/testing';
|
||||
import { App } from './app';
|
||||
import { provideRouter } from '@angular/router';
|
||||
|
||||
describe('App', () => {
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [App],
|
||||
providers: [provideRouter([])]
|
||||
}).compileComponents();
|
||||
});
|
||||
|
||||
it('should create the app', () => {
|
||||
const fixture = TestBed.createComponent(App);
|
||||
const app = fixture.componentInstance;
|
||||
expect(app).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -17,14 +17,16 @@ import { TranslateService } from '../../i18n/translate.service';
|
||||
`,
|
||||
styles: [`
|
||||
.dexar-back-btn {
|
||||
position: fixed;
|
||||
top: 76px;
|
||||
position: sticky;
|
||||
top: 72px;
|
||||
left: 20px;
|
||||
z-index: 100;
|
||||
background: none;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
padding: 4px;
|
||||
padding: 8px 4px;
|
||||
margin-bottom: -40px;
|
||||
width: fit-content;
|
||||
transition: transform 0.2s ease;
|
||||
|
||||
svg path {
|
||||
@@ -47,7 +49,7 @@ import { TranslateService } from '../../i18n/translate.service';
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.dexar-back-btn {
|
||||
top: 68px;
|
||||
top: 64px;
|
||||
left: 12px;
|
||||
|
||||
svg {
|
||||
|
||||
@@ -30,8 +30,8 @@
|
||||
<app-region-selector />
|
||||
<app-language-selector />
|
||||
|
||||
<a [routerLink]="'/cart' | langRoute" routerLinkActive="novo-cart-active" class="novo-cart" (click)="closeMenu()">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<a [routerLink]="'/cart' | langRoute" routerLinkActive="novo-cart-active" class="novo-cart" (click)="closeMenu()" [attr.aria-label]="'header.cart' | translate">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true">
|
||||
<circle cx="9" cy="21" r="1"></circle>
|
||||
<circle cx="20" cy="21" r="1"></circle>
|
||||
<path d="M1 1h4l2.68 13.39a2 2 0 0 0 2 1.61h9.72a2 2 0 0 0 2-1.61L23 6H6"></path>
|
||||
@@ -41,7 +41,7 @@
|
||||
}
|
||||
</a>
|
||||
|
||||
<button class="menu-toggle" (click)="toggleMenu()" [class.active]="menuOpen">
|
||||
<button class="menu-toggle" (click)="toggleMenu()" [class.active]="menuOpen" [attr.aria-label]="menuOpen ? 'Close menu' : 'Open menu'" [attr.aria-expanded]="menuOpen">
|
||||
<span></span>
|
||||
<span></span>
|
||||
<span></span>
|
||||
@@ -118,7 +118,7 @@
|
||||
</div>
|
||||
|
||||
<!-- Mobile Menu Toggle -->
|
||||
<button class="dexar-menu-toggle" (click)="toggleMenu()" [class.active]="menuOpen">
|
||||
<button class="dexar-menu-toggle" (click)="toggleMenu()" [class.active]="menuOpen" [attr.aria-label]="menuOpen ? 'Close menu' : 'Open menu'" [attr.aria-expanded]="menuOpen">
|
||||
<span></span>
|
||||
<span></span>
|
||||
<span></span>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<div class="language-selector">
|
||||
<button class="language-button" (click)="toggleDropdown()">
|
||||
<div class="language-selector" role="listbox">
|
||||
<button class="language-button" (click)="toggleDropdown()" (keydown)="onKeyDown($event)" aria-haspopup="listbox" [attr.aria-expanded]="dropdownOpen">
|
||||
<img [src]="languageService.getCurrentLanguage()?.flagSvg"
|
||||
[alt]="languageService.getCurrentLanguage()?.name"
|
||||
class="language-flag">
|
||||
@@ -13,6 +13,8 @@
|
||||
@for (lang of languageService.languages; track lang.code) {
|
||||
<button
|
||||
class="language-option"
|
||||
role="option"
|
||||
[attr.aria-selected]="languageService.currentLanguage() === lang.code"
|
||||
[class.active]="languageService.currentLanguage() === lang.code"
|
||||
[class.disabled]="!lang.enabled"
|
||||
[disabled]="!lang.enabled"
|
||||
|
||||
@@ -44,6 +44,15 @@ export class LanguageSelectorComponent {
|
||||
this.currencyOpen = false;
|
||||
}
|
||||
|
||||
onKeyDown(event: KeyboardEvent): void {
|
||||
if (event.key === 'Escape') {
|
||||
this.dropdownOpen = false;
|
||||
} else if (event.key === 'Enter' || event.key === ' ') {
|
||||
event.preventDefault();
|
||||
this.toggleDropdown();
|
||||
}
|
||||
}
|
||||
|
||||
@HostListener('document:click', ['$event'])
|
||||
onClickOutside(event: Event): void {
|
||||
if (!this.elementRef.nativeElement.contains(event.target)) {
|
||||
|
||||
@@ -31,13 +31,41 @@
|
||||
|
||||
<div class="qr-section">
|
||||
<p class="qr-hint">{{ 'auth.orScanQr' | translate }}</p>
|
||||
<div class="qr-container">
|
||||
<img [src]="'https://api.qrserver.com/v1/create-qr-code/?size=180x180&data=' + loginUrl()"
|
||||
alt="QR Code"
|
||||
width="180"
|
||||
height="180"
|
||||
loading="lazy" />
|
||||
</div>
|
||||
|
||||
@switch (qrStatus()) {
|
||||
@case ('loading') {
|
||||
<div class="qr-container qr-loading">
|
||||
<div class="spinner"></div>
|
||||
</div>
|
||||
}
|
||||
@case ('ready') {
|
||||
<div class="qr-container">
|
||||
<img [src]="'https://api.qrserver.com/v1/create-qr-code/?size=180x180&data=' + encodedQrUrl()"
|
||||
alt="QR Code"
|
||||
width="180"
|
||||
height="180"
|
||||
loading="eager" />
|
||||
</div>
|
||||
}
|
||||
@case ('expired') {
|
||||
<div class="qr-container qr-expired" (click)="refreshQr()">
|
||||
<svg width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<path d="M1 4v6h6M23 20v-6h-6"/>
|
||||
<path d="M20.49 9A9 9 0 0 0 5.64 5.64L1 10m22 4l-4.64 4.36A9 9 0 0 1 3.51 15"/>
|
||||
</svg>
|
||||
<span>{{ 'auth.qrExpired' | translate }}</span>
|
||||
</div>
|
||||
}
|
||||
@case ('error') {
|
||||
<div class="qr-container">
|
||||
<img [src]="'https://api.qrserver.com/v1/create-qr-code/?size=180x180&data=' + encodedQrUrl()"
|
||||
alt="QR Code"
|
||||
width="180"
|
||||
height="180"
|
||||
loading="lazy" />
|
||||
</div>
|
||||
}
|
||||
}
|
||||
</div>
|
||||
|
||||
<p class="login-note">{{ 'auth.loginNote' | translate }}</p>
|
||||
|
||||
@@ -122,6 +122,42 @@ h2 {
|
||||
display: block;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
&.qr-loading {
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 204px;
|
||||
height: 204px;
|
||||
|
||||
.spinner {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
border: 3px solid #e0e0e0;
|
||||
border-top-color: var(--accent-color, #497671);
|
||||
border-radius: 50%;
|
||||
animation: spin 0.8s linear infinite;
|
||||
}
|
||||
}
|
||||
|
||||
&.qr-expired {
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 8px;
|
||||
width: 204px;
|
||||
height: 204px;
|
||||
cursor: pointer;
|
||||
color: var(--text-secondary, #999);
|
||||
transition: color 0.2s ease;
|
||||
|
||||
&:hover {
|
||||
color: var(--accent-color, #497671);
|
||||
}
|
||||
|
||||
span {
|
||||
font-size: 13px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import { Component, ChangeDetectionStrategy, inject, signal, OnInit, OnDestroy } from '@angular/core';
|
||||
import { Component, ChangeDetectionStrategy, inject, signal, computed, effect, OnDestroy } from '@angular/core';
|
||||
import { AuthService } from '../../services/auth.service';
|
||||
import { CartService } from '../../services/cart.service';
|
||||
import { TranslatePipe } from '../../i18n/translate.pipe';
|
||||
import { getDiscountedPrice } from '../../utils/item.utils';
|
||||
|
||||
@Component({
|
||||
selector: 'app-telegram-login',
|
||||
@@ -9,17 +11,28 @@ import { TranslatePipe } from '../../i18n/translate.pipe';
|
||||
styleUrls: ['./telegram-login.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush
|
||||
})
|
||||
export class TelegramLoginComponent implements OnInit, OnDestroy {
|
||||
export class TelegramLoginComponent implements OnDestroy {
|
||||
private authService = inject(AuthService);
|
||||
private cartService = inject(CartService);
|
||||
|
||||
showDialog = this.authService.showLoginDialog;
|
||||
status = this.authService.status;
|
||||
|
||||
loginUrl = signal('');
|
||||
qrToken = signal('');
|
||||
qrStatus = signal<'loading' | 'ready' | 'expired' | 'error'>('loading');
|
||||
encodedQrUrl = computed(() => encodeURIComponent(this.loginUrl()));
|
||||
|
||||
private pollTimer?: ReturnType<typeof setInterval>;
|
||||
|
||||
ngOnInit(): void {
|
||||
this.loginUrl.set(this.authService.getTelegramLoginUrl());
|
||||
constructor() {
|
||||
effect(() => {
|
||||
if (this.showDialog()) {
|
||||
this.initQrLogin();
|
||||
} else {
|
||||
this.stopPolling();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
@@ -31,32 +44,87 @@ export class TelegramLoginComponent implements OnInit, OnDestroy {
|
||||
this.stopPolling();
|
||||
}
|
||||
|
||||
/** Open Telegram login link and start polling for session */
|
||||
openTelegramLogin(): void {
|
||||
window.open(this.loginUrl(), '_blank');
|
||||
this.startPolling();
|
||||
if (!this.pollTimer) {
|
||||
this.startPolling(this.qrToken());
|
||||
}
|
||||
}
|
||||
|
||||
/** Start polling the backend to detect when user completes Telegram auth */
|
||||
private startPolling(): void {
|
||||
refreshQr(): void {
|
||||
this.stopPolling();
|
||||
// Check every 3 seconds for up to 5 minutes
|
||||
this.initQrLogin();
|
||||
}
|
||||
|
||||
private initQrLogin(): void {
|
||||
this.qrStatus.set('loading');
|
||||
this.authService.createQrToken().subscribe({
|
||||
next: (res) => {
|
||||
this.loginUrl.set(res.url);
|
||||
this.qrToken.set(res.token);
|
||||
this.qrStatus.set('ready');
|
||||
this.startPolling(res.token);
|
||||
},
|
||||
error: () => {
|
||||
this.loginUrl.set(this.authService.getTelegramLoginUrl());
|
||||
this.qrStatus.set('error');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private startPolling(token: string): void {
|
||||
this.stopPolling();
|
||||
if (!token) return;
|
||||
|
||||
let checks = 0;
|
||||
this.pollTimer = setInterval(() => {
|
||||
checks++;
|
||||
if (checks > 100) { // 100 * 3s = 5 min
|
||||
if (checks > 100) {
|
||||
this.stopPolling();
|
||||
this.qrStatus.set('expired');
|
||||
return;
|
||||
}
|
||||
this.authService.checkSession();
|
||||
// If authenticated, stop polling and close dialog
|
||||
if (this.authService.isAuthenticated()) {
|
||||
this.stopPolling();
|
||||
this.authService.hideLogin();
|
||||
}
|
||||
|
||||
this.authService.pollQrToken(token).subscribe({
|
||||
next: (res) => {
|
||||
switch (res.status) {
|
||||
case 'confirmed':
|
||||
this.stopPolling();
|
||||
if (res.session) {
|
||||
this.syncCartAndComplete(res.session.sessionId);
|
||||
} else {
|
||||
this.authService.onTelegramLoginComplete();
|
||||
}
|
||||
break;
|
||||
case 'expired':
|
||||
this.stopPolling();
|
||||
this.qrStatus.set('expired');
|
||||
break;
|
||||
}
|
||||
},
|
||||
error: () => {
|
||||
// Network error — keep polling
|
||||
}
|
||||
});
|
||||
}, 3000);
|
||||
}
|
||||
|
||||
private syncCartAndComplete(sessionId: string): void {
|
||||
const cartItems = this.cartService.items().map(item => ({
|
||||
itemID: item.itemID,
|
||||
quantity: item.quantity,
|
||||
colour: item.colour || '',
|
||||
size: item.size || '',
|
||||
price: item.discount > 0
|
||||
? item.price * (1 - item.discount / 100)
|
||||
: item.price,
|
||||
}));
|
||||
|
||||
this.authService.syncCart(sessionId, cartItems).subscribe(() => {
|
||||
this.authService.onTelegramLoginComplete();
|
||||
});
|
||||
}
|
||||
|
||||
private stopPolling(): void {
|
||||
if (this.pollTimer) {
|
||||
clearInterval(this.pollTimer);
|
||||
|
||||
19
src/app/config/constants.ts
Normal file
19
src/app/config/constants.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
// Payment polling
|
||||
export const PAYMENT_POLL_INTERVAL_MS = 5000;
|
||||
export const PAYMENT_MAX_CHECKS = 36;
|
||||
export const PAYMENT_TIMEOUT_CLOSE_MS = 3000;
|
||||
export const PAYMENT_ERROR_CLOSE_MS = 4000;
|
||||
export const LINK_COPIED_DURATION_MS = 2000;
|
||||
|
||||
// Infinite scroll
|
||||
export const SCROLL_THRESHOLD_PX = 1200;
|
||||
export const SCROLL_DEBOUNCE_MS = 100;
|
||||
export const ITEMS_PER_PAGE = 50;
|
||||
|
||||
// Search
|
||||
export const SEARCH_DEBOUNCE_MS = 300;
|
||||
export const SEARCH_MIN_LENGTH = 3;
|
||||
|
||||
// Cache
|
||||
export const CACHE_DURATION_MS = 5 * 60 * 1000;
|
||||
export const CATEGORY_CACHE_DURATION_MS = 2 * 60 * 1000;
|
||||
@@ -205,5 +205,6 @@ export const en: Translations = {
|
||||
loginWithTelegram: 'Log in with Telegram',
|
||||
orScanQr: 'Or scan the QR code',
|
||||
loginNote: 'You will be redirected back after login',
|
||||
qrExpired: 'QR code expired. Click to refresh',
|
||||
},
|
||||
};
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Translations } from './translations';
|
||||
import { Translations } from './translations';
|
||||
|
||||
export const hy: Translations = {
|
||||
header: {
|
||||
@@ -205,5 +205,6 @@ export const hy: Translations = {
|
||||
loginWithTelegram: 'Մուտք Telegram-ով',
|
||||
orScanQr: 'Կամ սքանավորեք QR կոդը',
|
||||
loginNote: 'Մուտքից հետո դուք կվերաուղղվեք',
|
||||
qrExpired: 'QR կոդը հնացել է։ Սեղմեք՝ թարմացնելու համար',
|
||||
},
|
||||
};
|
||||
|
||||
@@ -205,5 +205,6 @@ export const ru: Translations = {
|
||||
loginWithTelegram: 'Войти через Telegram',
|
||||
orScanQr: 'Или отсканируйте QR-код',
|
||||
loginNote: 'После входа вы будете перенаправлены обратно',
|
||||
qrExpired: 'QR-код устарел. Нажмите, чтобы обновить',
|
||||
},
|
||||
};
|
||||
|
||||
@@ -203,5 +203,6 @@ export interface Translations {
|
||||
loginWithTelegram: string;
|
||||
orScanQr: string;
|
||||
loginNote: string;
|
||||
qrExpired: string;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -19,6 +19,25 @@ const REGION_HEADER_MAP: Record<string, string> = {
|
||||
'yerevan': 'Yerevan',
|
||||
};
|
||||
|
||||
const SESSION_STORAGE_KEY = 'web_session_id';
|
||||
|
||||
/** Generate a 32-char hex string (GUID without dashes) */
|
||||
function generateSessionId(): string {
|
||||
const bytes = new Uint8Array(16);
|
||||
crypto.getRandomValues(bytes);
|
||||
return Array.from(bytes, b => b.toString(16).padStart(2, '0')).join('');
|
||||
}
|
||||
|
||||
/** Get or create a persistent anonymous session ID */
|
||||
function getAnonymousSessionId(): string {
|
||||
let id = localStorage.getItem(SESSION_STORAGE_KEY);
|
||||
if (!id || id.length !== 32) {
|
||||
id = generateSessionId();
|
||||
localStorage.setItem(SESSION_STORAGE_KEY, id);
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
export const apiHeadersInterceptor: HttpInterceptorFn = (req, next) => {
|
||||
if (!req.url.startsWith(environment.apiUrl)) {
|
||||
return next(req);
|
||||
@@ -42,9 +61,7 @@ export const apiHeadersInterceptor: HttpInterceptorFn = (req, next) => {
|
||||
headers = headers.set('X-Language', LANG_HEADER_MAP[lang] ?? lang.toUpperCase());
|
||||
}
|
||||
headers = headers.set('Currency', currency || 'RUB');
|
||||
if (session?.sessionId) {
|
||||
headers = headers.set('WebSessionID', session.sessionId);
|
||||
}
|
||||
headers = headers.set('WebSessionID', session?.sessionId || getAnonymousSessionId());
|
||||
|
||||
return next(req.clone({ headers }));
|
||||
};
|
||||
|
||||
@@ -2,8 +2,9 @@ import { HttpInterceptorFn, HttpResponse } from '@angular/common/http';
|
||||
import { of } from 'rxjs';
|
||||
import { tap } from 'rxjs/operators';
|
||||
|
||||
import { CACHE_DURATION_MS, CATEGORY_CACHE_DURATION_MS } from '../config/constants';
|
||||
|
||||
const cache = new Map<string, { response: HttpResponse<unknown>, timestamp: number }>();
|
||||
const CACHE_DURATION = 5 * 60 * 1000; // 5 минут
|
||||
|
||||
export const cacheInterceptor: HttpInterceptorFn = (req, next) => {
|
||||
// Кэшируем только GET запросы
|
||||
@@ -11,12 +12,16 @@ export const cacheInterceptor: HttpInterceptorFn = (req, next) => {
|
||||
return next(req);
|
||||
}
|
||||
|
||||
// Кэшируем только запросы списка категорий (не товары категорий)
|
||||
const shouldCache = req.url.match(/\/category$/) !== null;
|
||||
if (!shouldCache) {
|
||||
// Кэшируем списки категорий, товары категорий и отдельные товары
|
||||
const isCategoryList = /\/category$/.test(req.url);
|
||||
const isCategoryItems = /\/category\/[^/?]+/.test(req.url);
|
||||
const isItem = /\/items\/[^/?]+/.test(req.url);
|
||||
if (!isCategoryList && !isCategoryItems && !isItem) {
|
||||
return next(req);
|
||||
}
|
||||
|
||||
const ttl = isCategoryList ? CACHE_DURATION_MS : CATEGORY_CACHE_DURATION_MS;
|
||||
|
||||
// Cleanup expired entries before checking
|
||||
cleanupExpiredCache();
|
||||
|
||||
@@ -25,7 +30,7 @@ export const cacheInterceptor: HttpInterceptorFn = (req, next) => {
|
||||
// Проверяем наличие и актуальность кэша
|
||||
if (cachedResponse) {
|
||||
const age = Date.now() - cachedResponse.timestamp;
|
||||
if (age < CACHE_DURATION) {
|
||||
if (age < ttl) {
|
||||
return of(cachedResponse.response.clone());
|
||||
} else {
|
||||
cache.delete(req.url);
|
||||
@@ -53,7 +58,7 @@ export function clearCache(): void {
|
||||
function cleanupExpiredCache(): void {
|
||||
const now = Date.now();
|
||||
for (const [url, data] of cache.entries()) {
|
||||
if (now - data.timestamp >= CACHE_DURATION) {
|
||||
if (now - data.timestamp >= CACHE_DURATION_MS) {
|
||||
cache.delete(url);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -661,8 +661,10 @@ function getAllVisibleItems(): any[] {
|
||||
return MOCK_ITEMS.filter(i => i.visible !== false);
|
||||
}
|
||||
|
||||
function getItemsByCategoryId(categoryID: number): any[] {
|
||||
return getAllVisibleItems().filter(i => i.categoryID === categoryID);
|
||||
function getItemsByCategoryId(categoryID: number | string): any[] {
|
||||
return getAllVisibleItems().filter(i =>
|
||||
i.categoryID === categoryID || i.subcategoryId === categoryID
|
||||
);
|
||||
}
|
||||
|
||||
function respond<T>(body: T, delayMs = 150) {
|
||||
@@ -689,18 +691,23 @@ export const mockDataInterceptor: HttpInterceptorFn = (req, next) => {
|
||||
}
|
||||
|
||||
// ── GET /category/:id (items for a category)
|
||||
const catItemsMatch = url.match(/\/category\/(\d+)$/);
|
||||
const catItemsMatch = url.match(/\/category\/([^/?]+)$/);
|
||||
if (catItemsMatch && req.method === 'GET') {
|
||||
const catId = parseInt(catItemsMatch[1], 10);
|
||||
const raw = catItemsMatch[1];
|
||||
const num = Number(raw);
|
||||
const catId = Number.isFinite(num) ? num : raw;
|
||||
const items = getItemsByCategoryId(catId);
|
||||
return respond(items);
|
||||
}
|
||||
|
||||
// ── GET /item/:id
|
||||
const itemMatch = url.match(/\/item\/(\d+)$/);
|
||||
const itemMatch = url.match(/\/item\/([^/?]+)$/);
|
||||
if (itemMatch && req.method === 'GET') {
|
||||
const itemId = parseInt(itemMatch[1], 10);
|
||||
const item = MOCK_ITEMS.find(i => i.itemID === itemId);
|
||||
const raw = itemMatch[1];
|
||||
const num = Number(raw);
|
||||
const item = MOCK_ITEMS.find(i =>
|
||||
Number.isFinite(num) ? i.itemID === num : i.id === raw
|
||||
);
|
||||
if (item) {
|
||||
return respond(item);
|
||||
}
|
||||
@@ -735,34 +742,28 @@ export const mockDataInterceptor: HttpInterceptorFn = (req, next) => {
|
||||
return respond([]);
|
||||
}
|
||||
|
||||
// ── POST /cart (add to cart / create payment)
|
||||
if (url.endsWith('/cart') && req.method === 'POST') {
|
||||
const body = req.body as any;
|
||||
if (body?.amount) {
|
||||
// Payment mock
|
||||
return respond({
|
||||
qrId: 'mock-qr-' + Date.now(),
|
||||
qrStatus: 'CREATED',
|
||||
qrExpirationDate: new Date(Date.now() + 180000).toISOString(),
|
||||
payload: 'https://example.com/pay/mock',
|
||||
qrUrl: 'https://api.qrserver.com/v1/create-qr-code/?size=300x300&data=mock-payment'
|
||||
}, 300);
|
||||
}
|
||||
return respond({ message: 'Added (mock)' });
|
||||
// ── POST /websession/:id (add to cart)
|
||||
if (url.match(/\/websession\/[^/]+$/) && req.method === 'POST') {
|
||||
return respond({
|
||||
sessionId: 'mock-session',
|
||||
Status: true,
|
||||
cart: req.body
|
||||
});
|
||||
}
|
||||
|
||||
// ── PATCH /cart
|
||||
if (url.endsWith('/cart') && req.method === 'PATCH') {
|
||||
return respond({ message: 'Updated (mock)' });
|
||||
// ── POST /websession/:id/qr (create payment QR)
|
||||
if (url.match(/\/websession\/[^/]+\/qr$/) && req.method === 'POST') {
|
||||
return respond({
|
||||
qrId: 'mock-qr-' + Date.now(),
|
||||
qrStatus: 'NEW',
|
||||
qrExpirationDate: new Date(Date.now() + 180000).toISOString(),
|
||||
Payload: 'https://example.com/pay/mock',
|
||||
qrUrl: 'https://api.qrserver.com/v1/create-qr-code/?size=300x300&data=mock-payment'
|
||||
}, 300);
|
||||
}
|
||||
|
||||
// ── DELETE /cart
|
||||
if (url.endsWith('/cart') && req.method === 'DELETE') {
|
||||
return respond({ message: 'Removed (mock)' });
|
||||
}
|
||||
|
||||
// ── POST /comment
|
||||
if (url.endsWith('/comment') && req.method === 'POST') {
|
||||
// ── POST /items/:id/callback (review)
|
||||
if (url.match(/\/items\/\d+\/callback$/) && req.method === 'POST') {
|
||||
return respond({ message: 'Review submitted (mock)' }, 200);
|
||||
}
|
||||
|
||||
@@ -771,8 +772,8 @@ export const mockDataInterceptor: HttpInterceptorFn = (req, next) => {
|
||||
return respond({ message: 'Email sent (mock)' }, 200);
|
||||
}
|
||||
|
||||
// ── GET /qr/payment/:id (always return success for testing)
|
||||
if (url.includes('/qr/payment/') && req.method === 'GET') {
|
||||
// ── GET /websession/:id/:qrId (check QR payment status)
|
||||
if (url.match(/\/websession\/[^/]+\/[^/]+$/) && !url.match(/\/websession\/[^/]+\/qr$/) && req.method === 'GET') {
|
||||
return respond({
|
||||
paymentStatus: 'SUCCESS',
|
||||
code: 'SUCCESS',
|
||||
@@ -785,8 +786,7 @@ export const mockDataInterceptor: HttpInterceptorFn = (req, next) => {
|
||||
paymentPurpose: '',
|
||||
createDate: new Date().toISOString(),
|
||||
order: 'mock-order',
|
||||
qrExpirationDate: new Date().toISOString(),
|
||||
phoneNumber: ''
|
||||
qrExpirationDate: new Date().toISOString()
|
||||
}, 500);
|
||||
}
|
||||
|
||||
|
||||
@@ -17,4 +17,9 @@ export interface TelegramAuthData {
|
||||
hash: string;
|
||||
}
|
||||
|
||||
export interface QrPollResponse {
|
||||
status: 'pending' | 'confirmed' | 'expired';
|
||||
session?: AuthSession;
|
||||
}
|
||||
|
||||
export type AuthStatus = 'unknown' | 'checking' | 'authenticated' | 'expired' | 'unauthenticated';
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { ItemName } from './item.model';
|
||||
|
||||
export interface Category {
|
||||
categoryID: number;
|
||||
name: string;
|
||||
@@ -5,7 +7,10 @@ export interface Category {
|
||||
icon?: string;
|
||||
wideBanner?: string;
|
||||
itemCount?: number;
|
||||
categoriesCount?: number;
|
||||
priority?: number;
|
||||
names?: ItemName[];
|
||||
translations?: Record<string, CategoryTranslation>;
|
||||
|
||||
// BackOffice API fields
|
||||
id?: string;
|
||||
|
||||
@@ -40,6 +40,8 @@ export interface Question {
|
||||
answer: string;
|
||||
upvotes: number;
|
||||
downvotes: number;
|
||||
like?: number;
|
||||
dislike?: number;
|
||||
}
|
||||
|
||||
/** Localized name entry from backend */
|
||||
@@ -60,6 +62,16 @@ export interface ItemAttribute {
|
||||
value: string;
|
||||
}
|
||||
|
||||
/** Item variant detail (price, size, colour per variant) */
|
||||
export interface ItemDetail {
|
||||
color?: string;
|
||||
colour?: string;
|
||||
size?: string;
|
||||
price: number;
|
||||
currency: string;
|
||||
remaining: number;
|
||||
}
|
||||
|
||||
export interface Item {
|
||||
categoryID: number;
|
||||
itemID: number;
|
||||
@@ -95,6 +107,8 @@ export interface Item {
|
||||
subcategoryId?: string;
|
||||
translations?: Record<string, ItemTranslation>;
|
||||
comments?: Comment[];
|
||||
visits?: number;
|
||||
itemDetails?: ItemDetail[];
|
||||
}
|
||||
|
||||
export interface CartItem extends Item {
|
||||
|
||||
@@ -46,12 +46,15 @@
|
||||
|
||||
<p class="item-description">{{ itemDesc(item) || '' }}...</p>
|
||||
|
||||
@if (item.colour || item.size) {
|
||||
@if (item.colour || (item.size && item.size.toLowerCase() !== 'default')) {
|
||||
<div class="cart-item-variants">
|
||||
@if (item.colour) {
|
||||
<span class="cart-variant">{{ 'itemDetail.colour' | translate }}: {{ item.colour }}</span>
|
||||
<span class="cart-variant cart-variant-colour">
|
||||
{{ 'itemDetail.colour' | translate }}:
|
||||
<span class="cart-colour-swatch" [style.background-color]="item.colour" [title]="item.colour"></span>
|
||||
</span>
|
||||
}
|
||||
@if (item.size) {
|
||||
@if (item.size && item.size.toLowerCase() !== 'default') {
|
||||
<span class="cart-variant">{{ 'itemDetail.size' | translate }}: {{ item.size }}</span>
|
||||
}
|
||||
</div>
|
||||
|
||||
@@ -368,6 +368,7 @@
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
margin-top: 4px;
|
||||
|
||||
.cart-variant {
|
||||
@@ -377,6 +378,18 @@
|
||||
padding: 3px 10px;
|
||||
border-radius: 6px;
|
||||
font-weight: 500;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.cart-colour-swatch {
|
||||
display: inline-block;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
border-radius: 50%;
|
||||
border: 1px solid rgba(0, 0, 0, 0.15);
|
||||
vertical-align: middle;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -484,6 +497,7 @@
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
margin-top: 4px;
|
||||
|
||||
.cart-variant {
|
||||
@@ -493,6 +507,18 @@
|
||||
padding: 3px 10px;
|
||||
border-radius: 6px;
|
||||
font-weight: 500;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.cart-colour-swatch {
|
||||
display: inline-block;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
border-radius: 50%;
|
||||
border: 1px solid rgba(0, 0, 0, 0.15);
|
||||
vertical-align: middle;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@ import { getDiscountedPrice, getMainImage, trackByItemId, getBadgeClass, getTran
|
||||
import { LangRoutePipe } from '../../pipes/lang-route.pipe';
|
||||
import { TranslatePipe } from '../../i18n/translate.pipe';
|
||||
import { TranslateService } from '../../i18n/translate.service';
|
||||
import { PAYMENT_POLL_INTERVAL_MS, PAYMENT_MAX_CHECKS, PAYMENT_TIMEOUT_CLOSE_MS, PAYMENT_ERROR_CLOSE_MS, LINK_COPIED_DURATION_MS } from '../../config/constants';
|
||||
|
||||
@Component({
|
||||
selector: 'app-cart',
|
||||
@@ -55,7 +56,7 @@ export class CartComponent implements OnDestroy {
|
||||
emailSubmitting = signal<boolean>(false);
|
||||
paidItems: CartItem[] = [];
|
||||
|
||||
maxChecks = 36; // 36 checks * 5 seconds = 180 seconds (3 minutes)
|
||||
maxChecks = PAYMENT_MAX_CHECKS;
|
||||
private pollingSubscription?: Subscription;
|
||||
private closeTimeout?: ReturnType<typeof setTimeout>;
|
||||
|
||||
@@ -181,51 +182,62 @@ export class CartComponent implements OnDestroy {
|
||||
}
|
||||
|
||||
createPayment(): void {
|
||||
const telegramUsername = this.getTelegramUsername();
|
||||
const userId = this.getUserId();
|
||||
const orderId = this.generateOrderId();
|
||||
const sessionId = this.authService.session()?.sessionId || '';
|
||||
if (!sessionId) {
|
||||
this.paymentStatus.set('timeout');
|
||||
return;
|
||||
}
|
||||
|
||||
const paymentData = {
|
||||
amount: this.totalPrice(),
|
||||
currency: this.langService.currentCurrency(),
|
||||
siteuserID: userId,
|
||||
siteorderID: orderId,
|
||||
redirectUrl: '',
|
||||
telegramUsername: telegramUsername,
|
||||
items: this.items().map((item: CartItem) => ({
|
||||
itemID: item.itemID,
|
||||
price: item.discount > 0
|
||||
? item.price * (1 - item.discount / 100)
|
||||
: item.price,
|
||||
name: item.name,
|
||||
quantity: item.quantity
|
||||
}))
|
||||
};
|
||||
// First sync cart items to server via websession, then create QR
|
||||
const cartItems = this.items().map((item: CartItem) => ({
|
||||
itemID: item.itemID,
|
||||
quantity: item.quantity,
|
||||
colour: item.colour || '',
|
||||
size: item.size || '',
|
||||
price: item.discount > 0
|
||||
? item.price * (1 - item.discount / 100)
|
||||
: item.price,
|
||||
}));
|
||||
|
||||
this.apiService.createPayment(paymentData).subscribe({
|
||||
next: (response) => {
|
||||
this.paymentId.set(response.qrId);
|
||||
this.qrCodeUrl.set(response.qrUrl);
|
||||
this.paymentUrl.set(response.payload);
|
||||
this.paymentStatus.set('waiting');
|
||||
this.startPolling();
|
||||
this.apiService.addToCart(sessionId, cartItems).subscribe({
|
||||
next: () => {
|
||||
this.apiService.createPayment(sessionId).subscribe({
|
||||
next: (response) => {
|
||||
this.paymentId.set(response.qrId);
|
||||
this.qrCodeUrl.set(response.qrUrl);
|
||||
this.paymentUrl.set(response.Payload);
|
||||
this.paymentStatus.set('waiting');
|
||||
this.startPolling();
|
||||
},
|
||||
error: (err) => {
|
||||
console.error('Error creating payment:', err);
|
||||
this.paymentStatus.set('timeout');
|
||||
if (this.closeTimeout) clearTimeout(this.closeTimeout);
|
||||
this.closeTimeout = setTimeout(() => {
|
||||
this.closePaymentPopup();
|
||||
}, PAYMENT_ERROR_CLOSE_MS);
|
||||
}
|
||||
});
|
||||
},
|
||||
error: (err) => {
|
||||
console.error('Error creating payment:', err);
|
||||
console.error('Error syncing cart:', err);
|
||||
this.paymentStatus.set('timeout');
|
||||
if (this.closeTimeout) clearTimeout(this.closeTimeout);
|
||||
this.closeTimeout = setTimeout(() => {
|
||||
this.closePaymentPopup();
|
||||
}, 4000);
|
||||
}, PAYMENT_ERROR_CLOSE_MS);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
startPolling(): void {
|
||||
this.pollingSubscription = interval(5000) // every 5 seconds
|
||||
this.stopPolling();
|
||||
this.pollingSubscription = interval(PAYMENT_POLL_INTERVAL_MS)
|
||||
.pipe(
|
||||
take(this.maxChecks), // maximum 36 checks (3 minutes)
|
||||
switchMap(() => {
|
||||
return this.apiService.checkPaymentStatus(this.paymentId());
|
||||
const sessionId = this.authService.session()?.sessionId || '';
|
||||
return this.apiService.checkPaymentStatus(sessionId, this.paymentId());
|
||||
})
|
||||
)
|
||||
.subscribe({
|
||||
@@ -245,17 +257,19 @@ export class CartComponent implements OnDestroy {
|
||||
if (this.paymentStatus() === 'waiting') {
|
||||
this.paymentStatus.set('timeout');
|
||||
// Close popup after showing timeout message
|
||||
if (this.closeTimeout) clearTimeout(this.closeTimeout);
|
||||
this.closeTimeout = setTimeout(() => {
|
||||
this.closePaymentPopup();
|
||||
}, 3000);
|
||||
}, PAYMENT_TIMEOUT_CLOSE_MS);
|
||||
}
|
||||
},
|
||||
error: (err) => {
|
||||
console.error('Error checking payment status:', err);
|
||||
// Continue checking even on error until time runs out
|
||||
if (this.closeTimeout) clearTimeout(this.closeTimeout);
|
||||
this.closeTimeout = setTimeout(() => {
|
||||
this.closePaymentPopup();
|
||||
}, 3000);
|
||||
}, PAYMENT_TIMEOUT_CLOSE_MS);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -271,34 +285,13 @@ export class CartComponent implements OnDestroy {
|
||||
if (url) {
|
||||
navigator.clipboard.writeText(url).then(() => {
|
||||
this.linkCopied.set(true);
|
||||
setTimeout(() => this.linkCopied.set(false), 2000);
|
||||
setTimeout(() => this.linkCopied.set(false), LINK_COPIED_DURATION_MS);
|
||||
}).catch(err => {
|
||||
console.error(this.i18n.t('cart.copyError'), err);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private getTelegramUsername(): string {
|
||||
if (typeof window !== 'undefined' && window.Telegram?.WebApp?.initDataUnsafe?.user) {
|
||||
const user = window.Telegram.WebApp.initDataUnsafe.user;
|
||||
return user.username || 'nontelegram';
|
||||
}
|
||||
return 'nontelegram';
|
||||
}
|
||||
|
||||
private getUserId(): string {
|
||||
if (typeof window !== 'undefined' && window.Telegram?.WebApp?.initDataUnsafe?.user) {
|
||||
return window.Telegram.WebApp.initDataUnsafe.user.id.toString();
|
||||
}
|
||||
return `web_${Date.now()}`;
|
||||
}
|
||||
|
||||
private generateOrderId(): string {
|
||||
const timestamp = Date.now();
|
||||
const random = Math.random().toString(36).substring(2, 8);
|
||||
return `order_${timestamp}_${random}`;
|
||||
}
|
||||
|
||||
submitEmail(): void {
|
||||
// Mark both fields as touched
|
||||
this.emailTouched.set(true);
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
@if (!error()) {
|
||||
<div class="items-grid">
|
||||
@for (item of items(); track trackByItemId($index, item)) {
|
||||
<div class="item-card">
|
||||
<div class="item-card" (mouseenter)="onItemHover(item.itemID)">
|
||||
<a [routerLink]="['/item', item.itemID] | langRoute" class="item-link">
|
||||
<div class="item-image">
|
||||
<img [src]="getMainImage(item)" [alt]="itemName(item)" loading="lazy" decoding="async" width="300" height="300" />
|
||||
@@ -52,19 +52,29 @@
|
||||
</div>
|
||||
</a>
|
||||
|
||||
<button class="add-to-cart-btn" (click)="addToCart(item.itemID, $event)">
|
||||
<button class="add-to-cart-btn" (click)="addToCart(item.itemID, $event)" [attr.aria-label]="('category.addToCart' | translate) + ': ' + item.name">
|
||||
{{ 'category.addToCart' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
@if (loading() && items().length > 0) {
|
||||
<div class="loading-more">
|
||||
<div class="spinner"></div>
|
||||
<p>{{ 'category.loadingMore' | translate }}</p>
|
||||
</div>
|
||||
}
|
||||
@if (loading() && items().length > 0) {
|
||||
@for (i of skeletonSlots; track i) {
|
||||
<div class="item-card skeleton-card">
|
||||
<div class="item-link">
|
||||
<div class="item-image skeleton-image"></div>
|
||||
<div class="item-details">
|
||||
<div class="skeleton-line skeleton-title"></div>
|
||||
<div class="skeleton-line skeleton-rating"></div>
|
||||
<div class="skeleton-line skeleton-price"></div>
|
||||
<div class="skeleton-line skeleton-stock"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="skeleton-btn"></div>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
</div>
|
||||
|
||||
@if (!hasMore() && items().length > 0) {
|
||||
<div class="no-more">
|
||||
|
||||
@@ -95,7 +95,7 @@
|
||||
|
||||
.items-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(4, 1fr);
|
||||
grid-template-columns: repeat(4, minmax(0, 1fr));
|
||||
gap: 30px;
|
||||
margin-bottom: 40px;
|
||||
width: 100%;
|
||||
@@ -103,8 +103,10 @@
|
||||
|
||||
.item-card {
|
||||
width: 100%;
|
||||
min-width: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
|
||||
&:hover {
|
||||
@@ -139,7 +141,7 @@
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: #f5f5f5;
|
||||
background: #f0f0f0;
|
||||
|
||||
img {
|
||||
width: 100%;
|
||||
@@ -147,7 +149,7 @@
|
||||
object-fit: contain;
|
||||
background: white;
|
||||
padding: 12px;
|
||||
transition: transform 0.3s ease;
|
||||
transition: transform 0.3s ease, opacity 0.3s ease;
|
||||
}
|
||||
|
||||
&:hover img {
|
||||
@@ -192,6 +194,7 @@
|
||||
margin: 0;
|
||||
line-height: 1.3;
|
||||
display: -webkit-box;
|
||||
line-clamp: 2;
|
||||
-webkit-line-clamp: 2;
|
||||
-webkit-box-orient: vertical;
|
||||
overflow: hidden;
|
||||
@@ -287,11 +290,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
.loading-more {
|
||||
text-align: center;
|
||||
padding: 40px 20px;
|
||||
}
|
||||
|
||||
.spinner {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
@@ -312,24 +310,77 @@
|
||||
padding: 40px 20px;
|
||||
}
|
||||
|
||||
// Skeleton loading cards
|
||||
.skeleton-card {
|
||||
pointer-events: none;
|
||||
|
||||
.skeleton-image {
|
||||
background: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
|
||||
background-size: 200% 100%;
|
||||
animation: shimmer 1.5s infinite;
|
||||
}
|
||||
|
||||
.skeleton-line {
|
||||
border-radius: 6px;
|
||||
background: linear-gradient(90deg, #e8e8e8 25%, #d8d8d8 50%, #e8e8e8 75%);
|
||||
background-size: 200% 100%;
|
||||
animation: shimmer 1.5s infinite;
|
||||
}
|
||||
|
||||
.skeleton-title {
|
||||
height: 16px;
|
||||
width: 80%;
|
||||
}
|
||||
|
||||
.skeleton-rating {
|
||||
height: 12px;
|
||||
width: 50%;
|
||||
}
|
||||
|
||||
.skeleton-price {
|
||||
height: 18px;
|
||||
width: 40%;
|
||||
margin-top: auto;
|
||||
}
|
||||
|
||||
.skeleton-stock {
|
||||
height: 6px;
|
||||
width: 60px;
|
||||
}
|
||||
|
||||
.skeleton-btn {
|
||||
height: 42px;
|
||||
background: linear-gradient(90deg, #5a8a85 25%, #497671 50%, #5a8a85 75%);
|
||||
background-size: 200% 100%;
|
||||
animation: shimmer 1.5s infinite;
|
||||
border-radius: 0 0 13px 13px;
|
||||
margin-top: -1px;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes shimmer {
|
||||
0% { background-position: 200% 0; }
|
||||
100% { background-position: -200% 0; }
|
||||
}
|
||||
|
||||
// Responsive
|
||||
@media (max-width: 1200px) {
|
||||
.items-grid {
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||
gap: 24px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 992px) {
|
||||
.items-grid {
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||
gap: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.items-grid {
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
@@ -353,7 +404,7 @@
|
||||
}
|
||||
|
||||
.items-grid {
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
|
||||
@@ -2,12 +2,14 @@ import { Component, OnInit, OnDestroy, signal, HostListener, ChangeDetectionStra
|
||||
import { DecimalPipe } from '@angular/common';
|
||||
import { ActivatedRoute, RouterLink } from '@angular/router';
|
||||
import { ApiService, CartService } from '../../services';
|
||||
import { PrefetchService } from '../../services/prefetch.service';
|
||||
import { Item } from '../../models';
|
||||
import { Subscription } from 'rxjs';
|
||||
import { getDiscountedPrice, getMainImage, trackByItemId, getBadgeClass, getTranslatedField } from '../../utils/item.utils';
|
||||
import { LanguageService } from '../../services/language.service';
|
||||
import { LangRoutePipe } from '../../pipes/lang-route.pipe';
|
||||
import { TranslatePipe } from '../../i18n/translate.pipe';
|
||||
import { SCROLL_THRESHOLD_PX, SCROLL_DEBOUNCE_MS, ITEMS_PER_PAGE } from '../../config/constants';
|
||||
|
||||
@Component({
|
||||
selector: 'app-category',
|
||||
@@ -24,7 +26,7 @@ export class CategoryComponent implements OnInit, OnDestroy {
|
||||
hasMore = signal(true);
|
||||
|
||||
private skip = 0;
|
||||
private readonly count = 50;
|
||||
private readonly count = ITEMS_PER_PAGE;
|
||||
private isLoadingMore = false;
|
||||
private routeSubscription?: Subscription;
|
||||
private scrollTimeout?: ReturnType<typeof setTimeout>;
|
||||
@@ -32,7 +34,8 @@ export class CategoryComponent implements OnInit, OnDestroy {
|
||||
constructor(
|
||||
private route: ActivatedRoute,
|
||||
private apiService: ApiService,
|
||||
private cartService: CartService
|
||||
private cartService: CartService,
|
||||
private prefetchService: PrefetchService
|
||||
) {}
|
||||
|
||||
ngOnInit(): void {
|
||||
@@ -91,12 +94,12 @@ export class CategoryComponent implements OnInit, OnDestroy {
|
||||
|
||||
this.scrollTimeout = setTimeout(() => {
|
||||
const scrollPosition = window.innerHeight + window.scrollY;
|
||||
const bottomPosition = document.documentElement.scrollHeight - 500;
|
||||
const bottomPosition = document.documentElement.scrollHeight - SCROLL_THRESHOLD_PX;
|
||||
|
||||
if (scrollPosition >= bottomPosition && !this.loading() && this.hasMore() && !this.isLoadingMore) {
|
||||
this.loadItems();
|
||||
}
|
||||
}, 100);
|
||||
}, SCROLL_DEBOUNCE_MS);
|
||||
}
|
||||
|
||||
addToCart(itemID: number, event: Event): void {
|
||||
@@ -105,6 +108,11 @@ export class CategoryComponent implements OnInit, OnDestroy {
|
||||
this.cartService.addItem(itemID);
|
||||
}
|
||||
|
||||
onItemHover(itemID: number): void {
|
||||
this.prefetchService.prefetchItem(itemID);
|
||||
}
|
||||
|
||||
readonly skeletonSlots = Array.from({ length: 8 });
|
||||
readonly getDiscountedPrice = getDiscountedPrice;
|
||||
readonly getMainImage = getMainImage;
|
||||
readonly trackByItemId = trackByItemId;
|
||||
|
||||
@@ -48,13 +48,13 @@
|
||||
<a [routerLink]="['/category', cat.categoryID] | langRoute" class="category-card">
|
||||
<div class="category-image">
|
||||
@if (cat.icon) {
|
||||
<img [src]="cat.icon" [alt]="cat.name" loading="lazy" decoding="async" />
|
||||
<img [src]="cat.icon" [alt]="categoryName(cat)" loading="lazy" decoding="async" />
|
||||
} @else {
|
||||
<div class="category-fallback">{{ cat.name.charAt(0) }}</div>
|
||||
<div class="category-fallback">{{ categoryName(cat).charAt(0) }}</div>
|
||||
}
|
||||
</div>
|
||||
<div class="category-info">
|
||||
<h3 class="category-name">{{ cat.name }}</h3>
|
||||
<h3 class="category-name">{{ categoryName(cat) }}</h3>
|
||||
</div>
|
||||
</a>
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ import { Subscription } from 'rxjs';
|
||||
import { LangRoutePipe } from '../../pipes/lang-route.pipe';
|
||||
import { TranslatePipe } from '../../i18n/translate.pipe';
|
||||
import { TranslateService } from '../../i18n/translate.service';
|
||||
import { getDiscountedPrice, getMainImage, trackByItemId, getBadgeClass, getTranslatedField } from '../../utils/item.utils';
|
||||
import { getDiscountedPrice, getMainImage, trackByItemId, getBadgeClass, getTranslatedField, getTranslatedCategoryName } from '../../utils/item.utils';
|
||||
|
||||
@Component({
|
||||
selector: 'app-subcategories',
|
||||
@@ -59,7 +59,7 @@ export class SubcategoriesComponent implements OnInit, OnDestroy {
|
||||
next: (cats) => {
|
||||
this.categories.set(cats);
|
||||
const parent = cats.find(c => c.categoryID === parentID);
|
||||
this.parentName.set(parent ? parent.name : this.i18n.t('home.categoriesTitle'));
|
||||
this.parentName.set(parent ? getTranslatedCategoryName(parent, this.langService.currentLanguage()) : this.i18n.t('home.categoriesTitle'));
|
||||
|
||||
// Check for nested subcategories from API response (backOffice format)
|
||||
const nested = parent?.subcategories || [];
|
||||
@@ -135,4 +135,6 @@ export class SubcategoriesComponent implements OnInit, OnDestroy {
|
||||
readonly getBadgeClass = getBadgeClass;
|
||||
|
||||
itemName(item: Item): string { return getTranslatedField(item, 'name', this.langService.currentLanguage()); }
|
||||
|
||||
categoryName(cat: Category): string { return getTranslatedCategoryName(cat, this.langService.currentLanguage()); }
|
||||
}
|
||||
|
||||
@@ -19,10 +19,23 @@
|
||||
<app-items-carousel />
|
||||
|
||||
@if (loading()) {
|
||||
<div class="novo-loading">
|
||||
<div class="novo-spinner"></div>
|
||||
<p>{{ 'home.loading' | translate }}</p>
|
||||
</div>
|
||||
<section class="novo-categories">
|
||||
<div class="novo-section-header">
|
||||
<div class="skeleton-line" style="height: 32px; width: 200px; margin: 0 auto 12px;"></div>
|
||||
<div class="skeleton-line" style="height: 18px; width: 300px; margin: 0 auto;"></div>
|
||||
</div>
|
||||
<div class="novo-categories-grid">
|
||||
@for (i of skeletonSlots; track i) {
|
||||
<div class="novo-category-card skeleton-card">
|
||||
<div class="novo-category-image skeleton-image"></div>
|
||||
<div class="novo-category-info">
|
||||
<div class="skeleton-line" style="height: 18px; width: 70%;"></div>
|
||||
<div class="skeleton-line" style="height: 18px; width: 20px;"></div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</section>
|
||||
}
|
||||
|
||||
@if (error()) {
|
||||
@@ -53,16 +66,18 @@
|
||||
<a [routerLink]="['/category', category.categoryID] | langRoute" class="novo-category-card">
|
||||
<div class="novo-category-image">
|
||||
@if (category.icon) {
|
||||
<img [src]="category.icon" [alt]="category.name" loading="lazy" />
|
||||
<img [src]="category.icon" [alt]="categoryName(category)" loading="lazy" />
|
||||
} @else {
|
||||
<div class="novo-category-placeholder">
|
||||
<span>{{ category.name.charAt(0) }}</span>
|
||||
<span>{{ categoryName(category).charAt(0) }}</span>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
<div class="novo-category-info">
|
||||
<h3>{{ category.name }}</h3>
|
||||
<span class="novo-category-arrow">→</span>
|
||||
<h3>{{ categoryName(category) }}</h3>
|
||||
@if (getItemCount(category.categoryID)) {
|
||||
<p class="novo-category-count">{{ 'home.itemsCount' | translate:{ count: getItemCount(category.categoryID) } }}</p>
|
||||
}
|
||||
</div>
|
||||
</a>
|
||||
}
|
||||
@@ -101,10 +116,20 @@
|
||||
<app-items-carousel />
|
||||
|
||||
@if (loading()) {
|
||||
<div class="dexar-loading">
|
||||
<div class="dexar-spinner"></div>
|
||||
<p>{{ 'home.loadingDexar' | translate }}</p>
|
||||
</div>
|
||||
<section class="dexar-categories">
|
||||
<div class="skeleton-line" style="height: 36px; width: 220px; margin-bottom: 40px;"></div>
|
||||
<div class="dexar-categories-grid">
|
||||
@for (i of skeletonSlots; track i) {
|
||||
<div class="dexar-category-card skeleton-card">
|
||||
<div class="dexar-category-image skeleton-image"></div>
|
||||
<div class="dexar-category-info">
|
||||
<div class="skeleton-line" style="height: 16px; width: 75%;"></div>
|
||||
<div class="skeleton-line" style="height: 12px; width: 40%; margin-top: 4px;"></div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</section>
|
||||
}
|
||||
|
||||
@if (error()) {
|
||||
@@ -131,15 +156,15 @@
|
||||
[class.dexar-category-card--wide]="isWideCategory(category.categoryID)">
|
||||
<div class="dexar-category-image">
|
||||
@if (isWideCategory(category.categoryID) && category.wideBanner) {
|
||||
<img [src]="category.wideBanner" [alt]="category.name" loading="lazy" decoding="async" />
|
||||
<img [src]="category.wideBanner" [alt]="categoryName(category)" loading="lazy" decoding="async" />
|
||||
} @else if (category.icon) {
|
||||
<img [src]="category.icon" [alt]="category.name" loading="lazy" decoding="async" />
|
||||
<img [src]="category.icon" [alt]="categoryName(category)" loading="lazy" decoding="async" />
|
||||
} @else {
|
||||
<div class="dexar-category-fallback">{{ category.name.charAt(0) }}</div>
|
||||
<div class="dexar-category-fallback">{{ categoryName(category).charAt(0) }}</div>
|
||||
}
|
||||
</div>
|
||||
<div class="dexar-category-info">
|
||||
<h3 class="dexar-category-name">{{ category.name }}</h3>
|
||||
<h3 class="dexar-category-name">{{ categoryName(category) }}</h3>
|
||||
<p class="dexar-category-count">{{ 'home.itemsCount' | translate:{ count: getItemCount(category.categoryID) } }}</p>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
@@ -298,8 +298,8 @@
|
||||
.novo-category-info {
|
||||
padding: 1.5rem;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
|
||||
h3 {
|
||||
font-size: 1.25rem;
|
||||
@@ -308,10 +308,12 @@
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.novo-category-arrow {
|
||||
font-size: 1.5rem;
|
||||
color: var(--primary-color);
|
||||
transition: transform 0.3s;
|
||||
.novo-category-count {
|
||||
font-weight: 600;
|
||||
font-size: clamp(11px, 1vw, 13px);
|
||||
color: var(--text-secondary);
|
||||
margin: 4px 0 0;
|
||||
line-height: 1.2;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -896,3 +898,26 @@
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
}
|
||||
|
||||
// Skeleton loading cards
|
||||
.skeleton-card {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.skeleton-image {
|
||||
background: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
|
||||
background-size: 200% 100%;
|
||||
animation: shimmer 1.5s infinite;
|
||||
}
|
||||
|
||||
.skeleton-line {
|
||||
border-radius: 6px;
|
||||
background: linear-gradient(90deg, #e8e8e8 25%, #d8d8d8 50%, #e8e8e8 75%);
|
||||
background-size: 200% 100%;
|
||||
animation: shimmer 1.5s infinite;
|
||||
}
|
||||
|
||||
@keyframes shimmer {
|
||||
0% { background-position: 200% 0; }
|
||||
100% { background-position: -200% 0; }
|
||||
}
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import { Component, OnInit, signal, computed, ChangeDetectionStrategy } from '@angular/core';
|
||||
import { Component, OnInit, OnDestroy, signal, computed, ChangeDetectionStrategy } from '@angular/core';
|
||||
import { Router, RouterLink } from '@angular/router';
|
||||
import { ApiService, LanguageService } from '../../services';
|
||||
import { Category } from '../../models';
|
||||
import { environment } from '../../../environments/environment';
|
||||
import { getTranslatedCategoryName } from '../../utils/item.utils';
|
||||
import { ItemsCarouselComponent } from '../../components/items-carousel/items-carousel.component';
|
||||
import { LangRoutePipe } from '../../pipes/lang-route.pipe';
|
||||
import { TranslatePipe } from '../../i18n/translate.pipe';
|
||||
@@ -14,13 +15,14 @@ import { TranslatePipe } from '../../i18n/translate.pipe';
|
||||
styleUrls: ['./home.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush
|
||||
})
|
||||
export class HomeComponent implements OnInit {
|
||||
export class HomeComponent implements OnInit, OnDestroy {
|
||||
brandName = environment.brandFullName;
|
||||
isnovo = environment.theme === 'novo';
|
||||
categories = signal<Category[]>([]);
|
||||
wideCategories = signal<Set<number>>(new Set());
|
||||
loading = signal(true);
|
||||
error = signal<string | null>(null);
|
||||
readonly skeletonSlots = Array.from({ length: 6 });
|
||||
|
||||
// Memoized computed values for performance
|
||||
topLevelCategories = computed(() => {
|
||||
@@ -56,6 +58,14 @@ export class HomeComponent implements OnInit {
|
||||
this.loadCategories();
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
this.pendingImages.forEach(img => {
|
||||
img.onload = null;
|
||||
img.onerror = null;
|
||||
});
|
||||
this.pendingImages.clear();
|
||||
}
|
||||
|
||||
loadCategories(): void {
|
||||
this.loading.set(true);
|
||||
this.apiService.getCategories().subscribe({
|
||||
@@ -84,13 +94,17 @@ export class HomeComponent implements OnInit {
|
||||
return this.wideCategories().has(categoryID);
|
||||
}
|
||||
|
||||
private pendingImages = new Set<HTMLImageElement>();
|
||||
|
||||
private detectWideImages(categories: Category[]): void {
|
||||
const topLevel = categories.filter(c => c.parentID === 0);
|
||||
topLevel.forEach(cat => {
|
||||
if (!cat.wideBanner) return;
|
||||
|
||||
const img = new Image();
|
||||
this.pendingImages.add(img);
|
||||
img.onload = () => {
|
||||
this.pendingImages.delete(img);
|
||||
const ratio = img.naturalWidth / img.naturalHeight;
|
||||
if (ratio > 2) {
|
||||
this.wideCategories.update(set => {
|
||||
@@ -100,6 +114,7 @@ export class HomeComponent implements OnInit {
|
||||
});
|
||||
}
|
||||
};
|
||||
img.onerror = () => this.pendingImages.delete(img);
|
||||
img.src = cat.wideBanner;
|
||||
});
|
||||
}
|
||||
@@ -109,6 +124,10 @@ export class HomeComponent implements OnInit {
|
||||
this.router.navigate([`/${lang}/search`]);
|
||||
}
|
||||
|
||||
categoryName(cat: Category): string {
|
||||
return getTranslatedCategoryName(cat, this.langService.currentLanguage());
|
||||
}
|
||||
|
||||
scrollToCatalog(): void {
|
||||
const target = document.getElementById('catalog');
|
||||
if (!target) return;
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
<div class="legal-page">
|
||||
<div class="legal-page">
|
||||
<div class="legal-container">
|
||||
<h1>About the company LLC «INT FIN LOGISTIC»</h1>
|
||||
<h1>About the companies LLC «INT FIN LOGISTIC» and LLC «INT FACTORING»</h1>
|
||||
|
||||
<section class="legal-section">
|
||||
<h2>About us</h2>
|
||||
<p>DexarMarket is a rapidly growing marketplace actively operating in the trade of various goods and services. The registration of the legal entity ООО "ИНТ ФИН ЛОГИСТИК" in accordance with Armenian legislation underscores the international focus of the business, as the company also successfully operates in the Russian market with all necessary credentials for legal activity in the Russian Federation.</p>
|
||||
<p>DexarMarket is a rapidly growing marketplace actively operating in the trade of various goods and services. The registration of the legal entities ООО "ИНТ ФИН ЛОГИСТИК" and ООО "ИНТ ФАКТОРИНГ" in accordance with Armenian legislation underscores the international focus of the business, as the companies also successfully operate in the Russian market with all necessary credentials for legal activity in the Russian Federation.</p>
|
||||
|
||||
<p>DEXARMARKET began its operations in Armenia, but expansion happened swiftly. By the summer of 2025, the platform had entered the Russian market, showing significant growth in popularity among partners and buyers from various regions of the world, including Russia, the United Arab Emirates, Turkey, China, Armenia, Kazakhstan, Kyrgyzstan, and other countries.</p>
|
||||
|
||||
@@ -65,8 +65,11 @@
|
||||
<p><strong>Director:</strong> Оганнисян Ашот Рафикович</p>
|
||||
<p><strong>Legal address:</strong><br>АРМЕНИЯ, 2301, КОТАЙКСКАЯ ОБЛАСТЬ, РАЗДАН, ХАЧАТРЯНА ул, 31, 4</p>
|
||||
<p><strong>Office in Armenia:</strong><br>0033, Ереван, улица Братьев Орбели, 47</p>
|
||||
<p><strong>Office in Russia:</strong><br>121059, Москва, наб. Тараса Шевченко, 3к2</p>
|
||||
|
||||
<p><strong>Key details:</strong><br>ИНН (RF): 9909697628<br>ИНН (Armenia): 03033502<br>КПП: 770287001<br>ОГРН: 85.110.1408711</p>
|
||||
<br>
|
||||
<p><strong>Full company name:</strong><br>ОБЩЕСТВО С ОГРАНИЧЕННОЙ ОТВЕТСТВЕННОСТЬЮ «ИНТ ФАКТОРИНГ»</p>
|
||||
<p><strong>ИНН:</strong> 9909697635</p>
|
||||
<p><strong>Banking details:</strong><br>Bank: АО "Райффайзенбанк"<br>Settlement account: 40807810500000002376<br>Correspondent account: 30101810200000000700<br>БИК: 044525700</p>
|
||||
<p><strong>Contact information:</strong><br>Phone (Russia): +7 (926) 459-31-57<br>Phone (Armenia): +374 94 86 18 16<br>Email: info@dexarmarket.ru<br>Website: www.dexarmarket.ru</p>
|
||||
</section>
|
||||
|
||||
@@ -1,54 +1,54 @@
|
||||
<div class="legal-page">
|
||||
<div class="legal-page">
|
||||
<div class="legal-container">
|
||||
<h1>«ИНТ ФИН ЛОГИСТИК» ՍՊԸ ընկերության մասին</h1>
|
||||
<h1>«ԻՆՏ ՖԻՆ ԼՈԳԻՍՏԻԿ» և «ԻՆՏ ՖԱԿՏՈՐԻՆԳ» ՍՊԸ ընկերությունների մասին</h1>
|
||||
|
||||
<section class="legal-section">
|
||||
<h2>Մեր մասին</h2>
|
||||
<p>DexarMarket-ը արագորեն զարգացող մարկեթփլեյս է, որն ակտիվորեն գործում է տարբեր ապրանքների և ծառայությունների առևտրի ոլորտում։ «ИНТ ФИН ЛОГИСТИК» ՍՊԸ իրավաբանական անձի գրանցումը, իրականացված Հայաստանի օրենսդրությանը համաձայն, ընդգծում է բիզնեսի միջազգային ուղղվածությունը, քանի որ ընկերությունը նաև հաջողությամբ գործում է ռուսական շուկայում։</p>
|
||||
<p>DexarMarket-ը արագ զարգացող առցանց առևտրային հարթակ է, որը գործում է տարբեր ապրանքների և ծառայությունների վաճառքի ոլորտում։ «ԻՆՏ ՖԻՆ ԼՈԳԻՍՏԻԿ» և «ԻՆՏ ՖԱԿՏՈՐԻՆԳ» ՍՊԸ-ների գրանցումը Հայաստանի օրենսդրությանը համապատասխան ընդգծում է բիզնեսի միջազգային ուղղվածությունը, քանի որ ընկերությունները հաջողությամբ աշխատում են նաև ռուսական շուկայում։</p>
|
||||
|
||||
<p>DEXARMARKET-ը իր գործունեությունը սկսել է հենց Հայաստանում, սակայն ընդլայնումը տեղի ունեցավ արագ։ 2025 թվականի ամռանը հարթակը մուտք գործեց ռուսական շուկա, ցույց տալով ժողովրդականության զգալի աճ գործընկերների և գնորդների շրջանում, ներառյալ Րուսաստանը, Միացյալ Արաբական Էմիրությունները, Թուրքիան, Չինաստանը, Հայաստանը, Ղազախստանը, Ղրղզստանը և այլ երկրները։</p>
|
||||
<p>DEXARMARKET-ը իր գործունեությունը սկսել է Հայաստանում, իսկ հետագա ընդլայնումը տեղի է ունեցել արագ տեմպերով։ 2025 թվականի ամռանը հարթակը մուտք գործեց ռուսական շուկա և կարճ ժամանակում զգալի ճանաչում ձեռք բերեց գործընկերների և գնորդների շրջանում Ռուսաստանում, Միացյալ Արաբական Էմիրություններում, Թուրքիայում, Չինաստանում, Հայաստանում, Ղազախստանում, Ղրղզստանում և այլ երկրներում։</p>
|
||||
|
||||
<p>Ընկերության հիմնական նպատակը որակյալ ծառայություններ մատուցելն է իր գործընկերներին և գնորդներին, ապահովելով գործարքների հարմարությունը և հուսալիությունը, ընդլայնելով ապրանքների և ծառայությունների տեսականիքը, ինչպես նաև պահպանելով հաճախորդների սպասարկման բարձր չափանիշները։</p>
|
||||
<p>Ընկերության հիմնական նպատակը գործընկերներին և գնորդներին որակյալ ծառայություններ մատուցելն է, գործարքների հարմարությունն ու հուսալիությունն ապահովելը, ապրանքների և ծառայությունների տեսականու ընդլայնումը, ինչպես նաև հաճախորդների սպասարկման բարձր չափանիշների պահպանումը։</p>
|
||||
|
||||
<p>Այսպիսով, DEXARMARKET-ը հաջող միջազգային նախագծի վառք օրինակ է, որը ցույց է տալիս հաջող զարգացում և ինտեգրացիա համաշխարհային մակարդակով։</p>
|
||||
<p>Այսպիսով, DEXARMARKET-ը հաջող միջազգային նախագծի օրինակ է, որը ցույց է տալիս կայուն զարգացում և արդյունավետ ինտեգրում միջազգային մակարդակում։</p>
|
||||
</section>
|
||||
|
||||
<section class="legal-section">
|
||||
<h2>Մեր առաքելությունը</h2>
|
||||
<p>Մենք ձգտում ենք ստեղծել յուրահատուկ էկոհամակարգ, որը ապահովում է առավելագույն հարմարություն և օգուտ մեր գործընկերներին DEXARMARKET հարթակում ապրանքներ տեղադրելիս։ Մենք առաջարկում ենք լայն շրջանակի լրացուցիչ ծառայություններ, որոնք օգնում են օպտիմալացնել մեր վաճառողների բիզնես գործընթացները։</p>
|
||||
<p>Մենք ձգտում ենք ստեղծել այնպիսի էկոհամակարգ, որը մեր գործընկերներին կապահովի առավելագույն հարմարություն և օգուտ DEXARMARKET հարթակում ապրանքներ տեղադրելիս։ Մենք առաջարկում ենք լրացուցիչ ծառայությունների լայն շրջանակ, որոնք օգնում են օպտիմալացնել վաճառողների բիզնես գործընթացները։</p>
|
||||
|
||||
<p>Գնորդների համար մենք ապահովում ենք հարմար մուտք դեպի որակյալ ապրանքների բազմազան տեսականիք գրավիչ գներով անմիջապես արտադրողներից և մատակարարներից։ Սա թույլ է տալիս հաճախորդներին խնայել ժամանակ և միջոցներ, ընտրելով շուկայի լավագույն առաջարկները։</p>
|
||||
<p>Գնորդներին մենք ապահովում ենք հարմար հասանելիություն դեպի որակյալ ապրանքների լայն տեսականի` գրավիչ գներով, անմիջապես արտադրողներից և մատակարարներից։ Սա հաճախորդներին թույլ է տալիս խնայել ժամանակ և միջոցներ` ընտրելով շուկայի լավագույն առաջարկները։</p>
|
||||
|
||||
<h3>Մեր հիմնական առաջնահերթություններն են՝</h3>
|
||||
<ul>
|
||||
<li>Ստեղծել թափանցիկ և արդյունավետ համակարգ վաճառողների և գնորդների միջև։</li>
|
||||
<li>Տրամադրել նորարարական լուծումներ՝ մեր գործընկերների մրցունակությունը բարձրացնելու և վաճառքները ավելացնելու համար։</li>
|
||||
<li>Ապահովել հաճախորդների սպասարկման և օգտատերների աջակցության բարձր մակարդակ համագործակցության բոլոր փուլերում։</li>
|
||||
<li>Ստեղծել թափանցիկ և արդյունավետ համագործակցության համակարգ վաճառողների և գնորդների միջև։</li>
|
||||
<li>Տրամադրել նորարարական լուծումներ` գործընկերների մրցունակությունը բարձրացնելու և վաճառքներն ավելացնելու համար։</li>
|
||||
<li>Ապահովել հաճախորդների սպասարկման և օգտատերերի աջակցության բարձր մակարդակ համագործակցության բոլոր փուլերում։</li>
|
||||
</ul>
|
||||
|
||||
<p>Մենք մշտապես աշխատում ենք մեր հարթակի ֆունկցիոնալության բարելավման վրա, ներդրելով նոր տեխնոլոգիաներ և գործիքներ, որպեսզի գնում և վաճառքի գործընթացը ավելի հարմար և շահավետ դարձնենք շուկայի բոլոր մասնակիցների համար։</p>
|
||||
<p>Մենք մշտապես աշխատում ենք հարթակի ֆունկցիոնալության բարելավման վրա` ներդնելով նոր տեխնոլոգիաներ և գործիքներ, որպեսզի գնումների և վաճառքի գործընթացը դարձնենք ավելի հարմար և շահավետ շուկայի բոլոր մասնակիցների համար։</p>
|
||||
</section>
|
||||
|
||||
<section class="legal-section">
|
||||
<h2>DEXARMARKET ընկերության պատմությունը</h2>
|
||||
|
||||
<p>DEXARMARKET ընկերությունը ստեղծվել է մասնագետների թիմի ջանքերի շնորհիվ, որոնք միավորվել էին ընդհանուր նպատակով և փորձով հիմնական ոլորտներում՝ տեղեկատվական-հաղորդակցական տեխնոլոգիաների (IT), տնտեսագիտության և առևտրային ոլորտի։ Հիմնադիրները հասկանում էին առաջատար տեխնոլոգիական լուծումների ինտեգրման և շուկայական գործընթացների խորը ըմբռնման կարևորությունը, ինչը հնարավորություն տվեց ձևավորել մարկեթփլեյսի զարգացման արդյունավետ հայեցակարգ։</p>
|
||||
<p>DEXARMARKET-ը ստեղծվել է մասնագետների թիմի ջանքերով, որոնք միավորվել էին ընդհանուր տեսլականի շուրջ և ունեին փորձ տեղեկատվական տեխնոլոգիաների, տնտեսագիտության և առևտրի ոլորտներում։ Հիմնադիրները հասկանում էին առաջատար տեխնոլոգիական լուծումների ինտեգրման և շուկայական գործընթացների խորքային ըմբռնման կարևորությունը, ինչը հնարավորություն տվեց ձևավորել հարթակի զարգացման արդյունավետ հայեցակարգ։</p>
|
||||
|
||||
<h3>Հիմնական փուլերը՝</h3>
|
||||
|
||||
<h4>Գաղափարի ծնունդը</h4>
|
||||
<p>Թիմը, որը ուներ խորը գիտելիքներ թվային բիզնեսի տրանսֆորմացիայի և տնտեսական գործընթացների ոլորտում, միավորվեց հավակնորդ նպատակի շուրջ՝ ստեղծել հարթակ, որը նպաստում է ձեռներկատիրության և առևտրի զարգացմանը միջազգային մակարդակով։</p>
|
||||
<p>Թիմը, որն ուներ խոր գիտելիքներ թվային բիզնեսի վերափոխման և տնտեսական գործընթացների ոլորտում, միավորվեց հավակնոտ նպատակի շուրջ` ստեղծել հարթակ, որը կնպաստի ձեռնարկատիրության և առևտրի զարգացմանը միջազգային մակարդակում։</p>
|
||||
|
||||
<h4>Հայեցակարգի մշակումը</h4>
|
||||
<p>Գիտակցելով, որ անհրաժեշտ է տրամադրել հարմար գործիքներ օնլայն բիզնեսի արդյունավետ կառավարման համար, թիմը սկսեց մարկեթփլեյսի յուրահատուկ մոդելի մշակում, հիմնված էլեկտրոնային առևտրի և մեծ տվյալների վերլուծության վերջին նվաճումների վրա։</p>
|
||||
<p>Գիտակցելով, որ առցանց բիզնեսի արդյունավետ կառավարման համար անհրաժեշտ են հարմար գործիքներ, թիմը սկսեց մշակել հարթակի յուրահատուկ մոդելը` հիմնված էլեկտրոնային առևտրի և մեծ տվյալների վերլուծության արդի հնարավորությունների վրա։</p>
|
||||
|
||||
<h4>Հարթակի գործարկումը</h4>
|
||||
<p>Օգտագործելով նորարարական լուծումներ տեղեկատվական ենթակառուցվածքում և տվյալների պաշտպանության հուսալի մեխանիզմներով, թիմը ստեղծեց կայուն թվային միջավայր, գրավիչ ձեռներկատերների և վերջնական սպառողների համար։</p>
|
||||
<p>Տեղեկատվական ենթակառուցվածքում կիրառելով նորարարական լուծումներ և տվյալների պաշտպանության հուսալի մեխանիզմներ` թիմը ստեղծեց կայուն թվային միջավայր, որը գրավիչ է ինչպես ձեռնարկատերերի, այնպես էլ վերջնական սպառողների համար։</p>
|
||||
|
||||
<h4>Միջազգային մակարդակ դուրս գալը</h4>
|
||||
<p>Ազգային շուկայում ճանաչում ստանալով՝ DEXARMARKET-ը սկսեց իր ակտիվ առաջմումը միջազգային շուկաներում, աստիճանաբար ընդգրկելով տարբեր տարածաշրջաններ և երկրներ, ստեղծելով պայմաններ փոքր և միջին բիզնեսի, ինչպես նաև խոշոր առևտրային ընկերությունների աճի համար։</p>
|
||||
<p>Տեղական շուկայում ճանաչում ձեռք բերելուց հետո DEXARMARKET-ը սկսեց ակտիվորեն ընդլայնվել միջազգային շուկաներում` աստիճանաբար ընդգրկելով տարբեր տարածաշրջաններ և երկրներ ու ստեղծելով աճի պայմաններ փոքր և միջին բիզնեսի, ինչպես նաև խոշոր առևտրային ընկերությունների համար։</p>
|
||||
|
||||
<p><strong>Այսօր DEXARMARKET-ը շարունակում է զարգանալ, կատարելագործելով իր տեխնոլոգիական հնարավորությունները և օգտատերներին առաջարկելով ավելի շատ առավելություններ և հնարավորություններ հաջող առևտրային գործունեության համար։</strong></p>
|
||||
<p><strong>Այսօր DEXARMARKET-ը շարունակում է զարգանալ, կատարելագործել իր տեխնոլոգիական հնարավորությունները և օգտատերերին առաջարկել ավելի շատ առավելություններ ու հնարավորություններ հաջող առևտրային գործունեության համար։</strong></p>
|
||||
</section>
|
||||
|
||||
<section class="legal-section">
|
||||
@@ -65,8 +65,10 @@
|
||||
<p><strong>Տնօրեն՝</strong> Оганнисян Ашот Рафикович</p>
|
||||
<p><strong>Իրավաբանական հասցե՝</strong><br>АРМЕНИЯ, 2301, КОТАЙКСКАЯ ОБЛАСТЬ, РАЗДАН, ХАЧАТРЯНА ул, 31, 4</p>
|
||||
<p><strong>Գրասենյակ Հայաստանում՝</strong><br>0033, Երևան, Եղբայրներ Օրբելի փողոց, 47</p>
|
||||
<p><strong>Գրասենյակ Ռուսաստանում՝</strong><br>121059, Москва, наб. Тараса Шевченко, 3к2</p>
|
||||
<p><strong>Հիմնական վավերապայմանները՝</strong><br>ՀՍՀ (ՌՄ)՝ 9909697628<br>ՀՍՀ (Հայաստան)՝ 03033502<br>ԿՊՊ՝ 770287001<br>ՕԳՌՆ՝ 85.110.1408711</p>
|
||||
<br>
|
||||
<p><strong>Կազմակերպության լիարժեք անվանումը՝</strong><br>ОБЩЕСТВО С ОГРАНИЧЕННОЙ ОТВЕТСТВЕННОСТЬЮ «ИНТ ФАКТОРИНГ»</p>
|
||||
<p><strong>ИНН:</strong> 9909697635</p>
|
||||
<p><strong>Բանկային վավերապայմանները՝</strong><br>Բանկ՝ АО "Райффайзенбанк"<br>Հաշվարկային հաշիվ՝ 40807810500000002376<br>Թղթակցային հաշիվ՝ 30101810200000000700<br>ԲԻԿ՝ 044525700</p>
|
||||
<p><strong>Կապի տեղեկատվություն՝</strong><br>Հեռախոս (Ռուսաստան)՝ +7 (926) 459-31-57<br>Հեռախոս (Հայաստան)՝ +374 94 86 18 16<br>Էլ. փոստ՝ info@dexarmarket.ru<br>Կայք՝ www.dexarmarket.ru</p>
|
||||
</section>
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
<div class="legal-page">
|
||||
<div class="legal-page">
|
||||
<div class="legal-container">
|
||||
<h1>О компании ООО «ИНТ ФИН ЛОГИСТИК»</h1>
|
||||
<h1>О компаниях ООО «ИНТ ФИН ЛОГИСТИК» и ООО «ИНТ ФАКТОРИНГ»</h1>
|
||||
|
||||
<section class="legal-section">
|
||||
<h2>О нас</h2>
|
||||
<p>Компания DexarMarket действительно представляет собой быстроразвивающийся маркетплейс, активно функционирующий в области торговли различными товарами и услугами. Регистрация юридического лица ООО "ИНТ ФИН ЛОГИСТИК", осуществленная согласно законодательству Армении, подчеркивает международную направленность бизнеса, поскольку компания также успешно работает на российском рынке, имея необходимые реквизиты для легальной деятельности в РФ.</p>
|
||||
<p>Компания DexarMarket действительно представляет собой быстроразвивающийся маркетплейс, активно функционирующий в области торговли различными товарами и услугами. Регистрация юридических лиц ООО "ИНТ ФИН ЛОГИСТИК" и ООО "ИНТ ФАКТОРИНГ", осуществленная согласно законодательству Армении, подчеркивает международную направленность бизнеса, поскольку компании также успешно работают на российском рынке, имея необходимые реквизиты для легальной деятельности в РФ.</p>
|
||||
|
||||
<p>Начало своей деятельности DEXARMARKET положил именно в Армении, однако расширение произошло стремительно. Уже летом 2025 года площадка вышла на российский рынок, показывая значительный рост популярности среди партнеров и покупателей из разных регионов мира, включая Россию, Объединённые Арабские Эмираты, Турцию, Китай, Армению, Казахстан, Кыргызстан и другие государства.</p>
|
||||
|
||||
@@ -65,8 +65,11 @@
|
||||
<p><strong>Директор:</strong> Оганнисян Ашот Рафикович</p>
|
||||
<p><strong>Юридический адрес:</strong><br>АРМЕНИЯ, 2301, КОТАЙКСКАЯ ОБЛАСТЬ, РАЗДАН, ХАЧАТРЯНА ул, 31, 4</p>
|
||||
<p><strong>Офис в Армении:</strong><br>0033, Ереван, улица Братьев Орбели, 47</p>
|
||||
<p><strong>Офис в России:</strong><br>121059, Москва, наб. Тараса Шевченко, 3к2</p>
|
||||
|
||||
<p><strong>Основные реквизиты:</strong><br>ИНН (РФ): 9909697628<br>ИНН (Армения): 03033502<br>КПП: 770287001<br>ОГРН: 85.110.1408711</p>
|
||||
<br>
|
||||
<p><strong>Полное наименование организации:</strong><br>ОБЩЕСТВО С ОГРАНИЧЕННОЙ ОТВЕТСТВЕННОСТЬЮ «ИНТ ФАКТОРИНГ»</p>
|
||||
<p><strong>ИНН:</strong> 9909697635</p>
|
||||
<p><strong>Банковские реквизиты:</strong><br>Банк: АО "Райффайзенбанк"<br>Расчетный счет: 40807810500000002376<br>Корр. счет: 30101810200000000700<br>БИК: 044525700</p>
|
||||
<p><strong>Контактная информация:</strong><br>Телефон (Россия): +7 (926) 459-31-57<br>Телефон (Армения): +374 94 86 18 16<br>Email: info@dexarmarket.ru<br>Сайт: www.dexarmarket.ru</p>
|
||||
</section>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<div class="legal-page">
|
||||
<div class="legal-page">
|
||||
<div class="legal-container">
|
||||
<h1>Contacts</h1>
|
||||
|
||||
@@ -11,6 +11,9 @@
|
||||
<h2>Company Details</h2>
|
||||
<p><strong>Company name:</strong> INT FIN LOGISTIC LLC</p>
|
||||
<p><strong>TIN:</strong> 9909697628</p>
|
||||
<br>
|
||||
<p><strong>Company name:</strong> INT FACTORING LLC</p>
|
||||
<p><strong>TIN:</strong> 9909697635</p>
|
||||
</section>
|
||||
|
||||
<section class="legal-section">
|
||||
@@ -35,7 +38,7 @@
|
||||
<section class="legal-section">
|
||||
<h2>Office Addresses</h2>
|
||||
<p><strong>Office in Armenia:</strong> 0033, Yerevan, Orbeli Brothers Street, 47</p>
|
||||
<p><strong>Office in Russia:</strong> 121059, Moscow, Taras Shevchenko Embankment, 3/2</p>
|
||||
|
||||
</section>
|
||||
|
||||
<section class="legal-section">
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<div class="legal-page">
|
||||
<div class="legal-page">
|
||||
<div class="legal-container">
|
||||
<h1>Կապ</h1>
|
||||
|
||||
@@ -11,6 +11,9 @@
|
||||
<h2>Կազմակերպության տվյալներ</h2>
|
||||
<p><strong>Անվանումը՝</strong> ՍՊԸ «ԻՆՏ ՖԻՆ ԼՈԳԻՍՏԻԿ»</p>
|
||||
<p><strong>ՀՍՀ՝</strong> 9909697628</p>
|
||||
<br>
|
||||
<p><strong>Անվանումը՝</strong> ՍՊԸ «ԻՆՏ ՖԱԿՏՈՌԻՆԳ»</p>
|
||||
<p><strong>ՀՍՀ՝</strong> 9909697635</p>
|
||||
</section>
|
||||
|
||||
<section class="legal-section">
|
||||
@@ -35,8 +38,7 @@
|
||||
<section class="legal-section">
|
||||
<h2>Գրասենյակների հասցեներ</h2>
|
||||
<p><strong>Գրասենյակ Հայաստանում՝</strong> 0033, Երևան, Եղբայրներ Օրբելի փողոց, 47</p>
|
||||
<p><strong>Գրասենյակ Ռուսաստանում՝</strong> 121059, Մոսկվա, Տարաս Շևչենկոի փողոց, 3կ2</p>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
<section class="legal-section">
|
||||
<h2>Տեխնիկական աջակցություն</h2>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<div class="legal-page">
|
||||
<div class="legal-page">
|
||||
<div class="legal-container">
|
||||
<h1>Контакты</h1>
|
||||
|
||||
@@ -11,6 +11,9 @@
|
||||
<h2>Реквизиты организации</h2>
|
||||
<p><strong>Наименование:</strong> ООО «ИНТ ФИН ЛОГИСТИК»</p>
|
||||
<p><strong>ИНН:</strong> 9909697628</p>
|
||||
<br>
|
||||
<p><strong>Наименование:</strong> ООО «ИНТ ФАКТОРИНГ»</p>
|
||||
<p><strong>ИНН:</strong> 9909697635</p>
|
||||
</section>
|
||||
|
||||
<section class="legal-section">
|
||||
@@ -35,7 +38,7 @@
|
||||
<section class="legal-section">
|
||||
<h2>Адреса офисов</h2>
|
||||
<p><strong>Офис в Армении:</strong> 0033, Ереван, улица Братьев Орбели, 47</p>
|
||||
<p><strong>Офис в России:</strong> 121059, Москва, наб. Тараса Шевченко, 3к2</p>
|
||||
|
||||
</section>
|
||||
|
||||
<section class="legal-section">
|
||||
|
||||
@@ -4,52 +4,52 @@
|
||||
|
||||
<section class="legal-section">
|
||||
<h2>1. Առաքման եղանակներ</h2>
|
||||
<p>1.1. <strong>Թվային ապրանքներ.</strong> DexarMarket հարթակն իրականացնում է թվային ապրանքների (լիցենզիային բանալիներ, էլեկտրոնային վկայականներ, թվային բովանդակություն և այլն) առաքումը Գնորդի կողմից նշված էլեկտրոնային փոստի հասցեին կամ հարթակում անձնական հաշվին։ վճարման հաստատմանից անմիջապես հետո։</p>
|
||||
<p>1.2. <strong>Նյութական ապրանքներ.</strong> Վաճառողն ինքնուրույն իրականացնում է նյութական ապրանքների առաքումը՝ ներգրավելով տրանսպորտային ընկերություններ և փոստային օպերատորներ՝ ներառյալ, բայց չսահմանափակվաթ՝ <strong>ՍԴԷԿ</strong>, <strong>Ռուսաստանի փոստ</strong>, <strong>Boxberry</strong>, <strong>DPD</strong>, <strong>Yandex.Առաքում</strong> և այլ փոխադրողներ՝ Գնորդի հետ համաձայնությամբ։</p>
|
||||
<p>1.3. Նյութական ապրանքների առաքման եղանակները, հասանելի կոնկրետ Պատվերի համար, որոշվում են Վաճառողի կողմից Պատվերի ձևակերպման պահին և կարող են ներառել՝</p>
|
||||
<p>1.1. <strong>Թվային ապրանքներ.</strong> DexarMarket հարթակը թվային ապրանքները (լիցենզիայի բանալիներ, էլեկտրոնային վկայականներ, թվային բովանդակություն և այլն) ուղարկում է Գնորդի նշած էլեկտրոնային փոստին կամ անձնական հաշվին` վճարումը հաստատվելուց անմիջապես հետո։</p>
|
||||
<p>1.2. <strong>Նյութական ապրանքներ.</strong> Նյութական ապրանքների առաքումը Վաճառողն իրականացնում է ինքնուրույն` ներգրավելով տրանսպորտային ընկերություններ և փոստային օպերատորներ, այդ թվում` բայց չսահմանափակվելով <strong>СДЭК</strong>, <strong>Почта России</strong>, <strong>Boxberry</strong>, <strong>DPD</strong>, <strong>Yandex.Доставка</strong> և այլ փոխադրողներով` Գնորդի հետ համաձայնեցմամբ։</p>
|
||||
<p>1.3. Կոնկրետ պատվերի համար հասանելի առաքման եղանակները որոշվում են Վաճառողի կողմից պատվերի ձևակերպման պահին և կարող են ներառել`</p>
|
||||
<ul>
|
||||
<li>սուրհանդարակային առաքում (ՍԴԷԿ, DPD, Yandex.Առաքում, այլ սուրհանդարակային ծառայություններ)։</li>
|
||||
<li>առաքում ստացման կետ (Boxberry, ՍԴԷԿ, Հայփոստ)։</li>
|
||||
<li>փոստային առաքում (Հայփոստ)։</li>
|
||||
<li>ինքնավերցնել (եթե կիրառելի է տվյալ ապրանքի համար)։</li>
|
||||
<li>սուրհանդակային առաքում (СДЭК, DPD, Yandex.Доставка և այլ սուրհանդակային ծառայություններ),</li>
|
||||
<li>առաքում ստացման կետ (Boxberry, СДЭК, Почта России),</li>
|
||||
<li>փոստային առաքում (Почта России),</li>
|
||||
<li>ինքնուրույն ստացում, եթե դա կիրառելի է տվյալ ապրանքի համար։</li>
|
||||
</ul>
|
||||
<p>1.4. Առաքման կոնկրետ եղանակի ընտրությունը կատարվում է Գնորդի կողմից Պատվերի ձևակերպման գործընթացում՝ Վաճառողի առաիադրած հասանելի տարբերակների շրիանակում։</p>
|
||||
<p>1.4. Առաքման կոնկրետ եղանակը Գնորդն ընտրում է պատվերի ձևակերպման ընթացքում` Վաճառողի առաջարկած հասանելի տարբերակներից։</p>
|
||||
</section>
|
||||
|
||||
<section class="legal-section">
|
||||
<h2>2. Առաքման արժեքը</h2>
|
||||
<p>2.1. <strong>Թվային ապրանքներ.</strong> Թվային ապրանքների առաքումն անվճար է։</p>
|
||||
<p>2.2. <strong>Նյութական ապրանքներ.</strong> Նյութական ապրանքների առաքման արժեքը որոշվում է Վաճառողի կողմից՝ կախված առաքման եղանակից, առաքման քաշից և չափսերից, առաքման հասցեից և փոխադրողի գործող սակագներից՝ Պատվերի ձևակերպման պահին։</p>
|
||||
<p>2.3. Նյութական ապրանքների առաքման վերջնական արժեքը ցուցադրվում է Գնորդին մինչև Պատվերի հաստատումը և ներառվում է վճարման ընդհանուր գումարում։</p>
|
||||
<p>2.4. Ակցիաների և հատուկ առածների դեպքում առաքումը կարող է իրականացվել անվճար՝ ակցիայի նկարգրում նշված պայմաններին համապատասխան։</p>
|
||||
<p>2.2. <strong>Նյութական ապրանքներ.</strong> Նյութական ապրանքների առաքման արժեքը որոշվում է Վաճառողի կողմից` կախված ընտրված եղանակից, ծանրոցի քաշից ու չափերից, առաքման հասցեից և փոխադրողի գործող սակագներից պատվերի ձևակերպման պահին։</p>
|
||||
<p>2.3. Նյութական ապրանքների առաքման վերջնական արժեքը ցուցադրվում է Գնորդին մինչև պատվերի հաստատումը և ներառվում է վճարման ընդհանուր գումարում։</p>
|
||||
<p>2.4. Ակցիաների և հատուկ առաջարկների դեպքում առաքումը կարող է իրականացվել անվճար` ակցիայի նկարագրության մեջ նշված պայմաններին համապատասխան։</p>
|
||||
</section>
|
||||
|
||||
<section class="legal-section">
|
||||
<h2>3. Առաքման ժամկետները</h2>
|
||||
<p>3.1. <strong>Թվային ապրանքներ.</strong> Թվային ապրանքների առաքումն իրականացվում է անհապաղ (մի քանի րոպեի ընթացքում) վճարման հաստատմանից հետո։ Առանձին դեպքերում ժամկետը կարող է կազմել մինչև 24 ժամ։</p>
|
||||
<p>3.2. <strong>Նյութական ապրանքներ.</strong> Նյութական ապրանքների առաքման մոտավոր ժամկետները Ռուսաստանի Դաշնության տարածքում կազմում են 1 (մեկ) մինչև 14 (տասնչորս) աշխատանքային օր՝ առաքմանը փոխադրողին հանձնելու պահից։</p>
|
||||
<p>3.3. Նշված ժամկետները մոտավոր են և կարող են փոխվել՝ կախված առաքման տարածաշրից, փոխադրողի աշխատանքից, եղանակի պայմաններից, հանգստյան և տոնական օրերից։</p>
|
||||
<p>3.4. Նյութական ապրանքների առաքման ճշգրիտ ժամկետը հաշվարկվում է ավտոմատ կերպով Պատվերի ձևակերպման ժամանակ՝ ընտրված փոխադրողի տվյալների հիման վրա և հաղորդվում է Գնորդին։</p>
|
||||
<p>3.5. Վաճառողը պատասխանատվություն չի կրում առաքման ժամկետների խախտման համար՝ պատճառված փոխադրողի գործողությամբ կամ անգործությամբ, անհաղթահարելի ուժի հանգամանքներով կամ Վաճառողից անկախ այլ պատճառներով։</p>
|
||||
<p>3.1. <strong>Թվային ապրանքներ.</strong> Թվային ապրանքների առաքումն իրականացվում է անհապաղ (մի քանի րոպեի ընթացքում) վճարման հաստատումից հետո։ Առանձին դեպքերում ժամկետը կարող է հասնել մինչև 24 ժամի։</p>
|
||||
<p>3.2. <strong>Նյութական ապրանքներ.</strong> Նյութական ապրանքների առաքման մոտավոր ժամկետը Ռուսաստանի Դաշնության տարածքում կազմում է 1-ից 14 աշխատանքային օր` ապրանքը փոխադրողին հանձնելու պահից։</p>
|
||||
<p>3.3. Նշված ժամկետները մոտավոր են և կարող են փոխվել` կախված առաքման տարածաշրջանից, փոխադրողի աշխատանքից, եղանակային պայմաններից, հանգստյան և տոնական օրերից։</p>
|
||||
<p>3.4. Նյութական ապրանքների առաքման ճշգրիտ ժամկետը հաշվարկվում է ավտոմատ կերպով պատվերի ձևակերպման ընթացքում` ընտրված փոխադրողի տվյալների հիման վրա և հաղորդվում է Գնորդին։</p>
|
||||
<p>3.5. Վաճառողը պատասխանատվություն չի կրում առաքման ժամկետների խախտման համար, եթե դա պայմանավորված է փոխադրողի գործողություններով կամ անգործությամբ, ֆորս-մաժորային հանգամանքներով կամ Վաճառողից անկախ այլ պատճառներով։</p>
|
||||
</section>
|
||||
|
||||
<section class="legal-section">
|
||||
<h2>4. Ապրանքի հանձնման և ընդունման պայմանները</h2>
|
||||
<p>4.1. Ապրանքը հանձնվում է Գնորդին կամ նրա նշանակած անձին՝ փոխադրողի կողմից՝ ընտրված առաքման եղանակի պայմաններին համապատասխան։</p>
|
||||
<p>4.2. Ապրանքի պատահական կորստի կամ վնասվելու ռիսկը անցնում է Գնորդին՝ Ապրանքի փաստացի հանձնման պահից։</p>
|
||||
<p>4.3. Ապրանքը ստանալիս Գնորդը պարտավոր է՝</p>
|
||||
<p>4.1. Ապրանքը փոխադրողի կողմից հանձնվում է Գնորդին կամ նրա կողմից նշանակված անձին` ընտրված առաքման եղանակի պայմաններին համապատասխան։</p>
|
||||
<p>4.2. Ապրանքի պատահական կորստի կամ վնասման ռիսկը անցնում է Գնորդին` ապրանքի փաստացի հանձնման պահից։</p>
|
||||
<p>4.3. Ապրանքը ստանալիս Գնորդը պարտավոր է`</p>
|
||||
<ul>
|
||||
<li>ստուգել փաթեթավորման ամբողինությունը և Ապրանքի անվանման ու քանակի համապատասխանությունը ուղեկցող փաստաթղթերին։</li>
|
||||
<li>փաթեթավորման վնասվելու, պակասի կամ ապրանքի անհամապատասխանության դեպքում՝ կազմել ակտ փոխադրողի ներկայացուցչի ներկայությամբ։</li>
|
||||
<li>պրետենզիաների բացակայության դեպքում՝ ստորագրել փոխադրողի փաստաթղթերում՝ ծանոթացնելով, որ Ապրանքը ստացվել է պատշած վիժակում։</li>
|
||||
<li>ստուգել փաթեթավորման ամբողջականությունը և ապրանքի անվանման ու քանակի համապատասխանությունը ուղեկցող փաստաթղթերին,</li>
|
||||
<li>փաթեթավորման վնասման, պակասի կամ ապրանքի անհամապատասխանության դեպքում` կազմել ակտ փոխադրողի ներկայացուցչի ներկայությամբ,</li>
|
||||
<li>եթե պահանջներ չկան` ստորագրել փոխադրողի փաստաթղթերը` հաստատելով, որ ապրանքը ստացվել է պատշաճ վիճակում։</li>
|
||||
</ul>
|
||||
<p>4.4. Ապրանքի առաքումը իրականացվում է Վաճառողի կողմից Պատվերի հաստատմանից և վճարման ստացմանից (լիարժեք կամ մասնակի) հետո՝ կոնկրետ Պատվերի պայմաններին համապատասխան։</p>
|
||||
<p>4.5. Վաճառողը պատասխանատվություն չի կրում Ապրանքի կորստի, վնասվելու կամ ուշացման համար փոխադրման ընթացքում՝ եթե դրանք պատճառված են փոխադրողի գործողությամբ կամ անգործությամբ։ Այդ դեպքերում Գնորդը իրավունք ունի պրետենզիա ներկայացնել անմիիապես փոխադրողին՝ օրենքով սահմանված կարգով, իսկ Վաճառողը պարտավորվում է աջակցել վեճի կարգավորմանը ողի սահմաններում։</p>
|
||||
<p>4.4. Ապրանքի առաքումը կատարվում է Վաճառողի կողմից պատվերի հաստատումից և վճարման ստացումից (ամբողջությամբ կամ մասնակի) հետո` տվյալ պատվերի պայմաններին համապատասխան։</p>
|
||||
<p>4.5. Վաճառողը պատասխանատվություն չի կրում ապրանքի կորստի, վնասման կամ ուշացման համար փոխադրման ընթացքում, եթե դրանք պատճառվել են փոխադրողի գործողությամբ կամ անգործությամբ։ Այդ դեպքերում Գնորդն իրավունք ունի օրենքով սահմանված կարգով պահանջ ներկայացնել անմիջապես փոխադրողին, իսկ Վաճառողը պարտավորվում է ողջամիտ սահմաններում աջակցել վեճի կարգավորմանը։</p>
|
||||
</section>
|
||||
|
||||
<section class="legal-section">
|
||||
<h2>5. Կապի տեղեկատվություն</h2>
|
||||
<p>Առաքման հարցերով դիմեք՝</p>
|
||||
<h2>5. Կոնտակտային տվյալներ</h2>
|
||||
<p>Առաքման հետ կապված հարցերով կարող եք դիմել`</p>
|
||||
<ul>
|
||||
<li><strong>Էլ. փոստ՝</strong> <a href="mailto:info@dexarmarket.ru">info@dexarmarket.ru</a></li>
|
||||
<li><strong>Հեռախոս (Ռուսաստան)՝</strong> <a href="tel:+79264593157">+7 (926) 459-31-57</a></li>
|
||||
|
||||
@@ -6,18 +6,18 @@
|
||||
<h2>Ընդհանուր հարցեր</h2>
|
||||
|
||||
<div class="faq-item">
|
||||
<h3>Ինչ է DexarMarket-ը։</h3>
|
||||
<p>DexarMarket-ը օնլայն հարթակ է, որտեղ անկախ վաճառողները տեղադրում են իրենց ապրանքներն ու ծառայությունները։ Մեր նպատակն է ապահովել հարմար ու անվտանգ միջավայր գնումների համար — մենք ինքներս ապրանքներ չենք արտադրում ու չենք վաճառում։</p>
|
||||
<h3>Ի՞նչ է DexarMarket-ը։</h3>
|
||||
<p>DexarMarket-ը առցանց հարթակ է, որտեղ անկախ վաճառողները տեղադրում են իրենց ապրանքներն ու ծառայությունները։ Մեր նպատակը հարմար և անվտանգ միջավայր ապահովելն է գնումների համար. մենք ինքներս ապրանք չենք արտադրում և չենք վաճառում։</p>
|
||||
</div>
|
||||
|
||||
<div class="faq-item">
|
||||
<h3>Ինչպես գրանցվել հարթակում։</h3>
|
||||
<p>Գրանցվելը հեշտ է՝ բացեք մեր հավելվածը Telegram-ում։ Ձեր պրոֆիլը կստեղծվի ավտոմատ կերպով մուտք գործելուց հետո։</p>
|
||||
<h3>Ինչպե՞ս գրանցվել հարթակում։</h3>
|
||||
<p>Գրանցվելը շատ հեշտ է. բացեք մեր հավելվածը Telegram-ում։ Մուտք գործելուց հետո ձեր պրոֆիլը կստեղծվի ավտոմատ կերպով։</p>
|
||||
</div>
|
||||
|
||||
<div class="faq-item">
|
||||
<h3>Անվտանգ է գնել կայքում։</h3>
|
||||
<p>Անպայմանորեն՝ Բոլոր գործարքները պաշտպանված են ժամանակակից գաղտնագրման տեխնոլոգիաներով (PCI DSS և 3D Secure)։ Ձեր բանկային տվյալները պահվում են ապահով կերպով՝ անջատորեն մեր համակարգից։</p>
|
||||
<h3>Անվտանգ է արդյո՞ք գնում կատարել կայքում։</h3>
|
||||
<p>Այո։ Բոլոր գործարքները պաշտպանված են ժամանակակից գաղտնագրման տեխնոլոգիաներով (PCI DSS և 3D Secure)։ Ձեր բանկային տվյալները պահվում են անվտանգ և մեր համակարգից առանձնացված միջավայրում։</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
@@ -25,25 +25,25 @@
|
||||
<h2>Պատվերի ձևակերպում</h2>
|
||||
|
||||
<div class="faq-item">
|
||||
<h3>Ինչպես կատարել գնում։</h3>
|
||||
<h3>Ինչպե՞ս կատարել գնում։</h3>
|
||||
<p>
|
||||
1️⃣ Գտեք ձեզհամած ապրանքը և ավելացրեք զամբյուղին։<br>
|
||||
1️⃣ Գտեք ձեզ դուր եկած ապրանքը և ավելացրեք այն զամբյուղում։<br>
|
||||
2️⃣ Բացեք զամբյուղը և սեղմեք «Ձևակերպել պատվերը»։<br>
|
||||
3️⃣ Նշեք առաքման հասցեն և կապի տեղեկատվությունը։<br>
|
||||
3️⃣ Նշեք առաքման հասցեն և կապի տվյալները։<br>
|
||||
4️⃣ Ընտրեք հարմար վճարման եղանակ։<br>
|
||||
5️⃣ Ծանոթացեք և հաստատեք հանրային օֆերտան։<br>
|
||||
5️⃣ Ծանոթացեք և հաստատեք հանրային օֆերտայի պայմանները։<br>
|
||||
6️⃣ Ավարտեք վճարումը։
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="faq-item">
|
||||
<h3>Կարելի։ է փոփոխություններ կատարել գնումից հետո։</h3>
|
||||
<p>Եթե վաճառողը դեռ չի ուղարկել ապրանքը, գրեք մեզ աջակցության ծառայություն — մենք կօգնենք ճշտել պատվերը։ Սակայն ապրանքը ուղարկելուց հետո փոփոխություն հնարավոր չէ։</p>
|
||||
<h3>Կարելի՞ է փոփոխություններ կատարել գնումից հետո։</h3>
|
||||
<p>Եթե վաճառողը դեռ չի ուղարկել ապրանքը, գրեք աջակցության ծառայությանը, և մենք կօգնենք ճշտել պատվերը։ Սակայն ապրանքի ուղարկումից հետո փոփոխություններ կատարել այլևս հնարավոր չէ։</p>
|
||||
</div>
|
||||
|
||||
<div class="faq-item">
|
||||
<h3>Ինչպես հրաժարվել պատվերից։</h3>
|
||||
<p>Կապվեք մեզ հետ կամ անմիջապես վաճառողի հետ պատվերների չատերով։ Մինչև ծանրը չի ուղարկվել, հնարավոր է հրաժարվել լիովին գումարի վերադարձով։</p>
|
||||
<h3>Ինչպե՞ս հրաժարվել պատվերից։</h3>
|
||||
<p>Կապ հաստատեք մեզ հետ կամ անմիջապես վաճառողի հետ պատվերի չատի միջոցով։ Քանի դեռ ապրանքը չի ուղարկվել, պատվերից կարելի է հրաժարվել ամբողջ գումարի վերադարձով։</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
@@ -51,36 +51,36 @@
|
||||
<h2>Վճարում 💳</h2>
|
||||
|
||||
<div class="faq-item">
|
||||
<h3>Ինչ վճարման եղանակներ կան։</h3>
|
||||
<p>Ընդունվում են՝</p>
|
||||
<h3>Ի՞նչ վճարման եղանակներ կան։</h3>
|
||||
<p>Ընդունվում են`</p>
|
||||
<ul>
|
||||
<li>Visa, MasterCard, ՄԻՌ բանկային քարտեր,</li>
|
||||
<li>Արագ վճարման համակարգ (ՍԲՊ),</li>
|
||||
<li>Ելեկտրոնային դրամապանակներ՝ YooMoney, QIWI,</li>
|
||||
<li>Կանխիկ՝ ստանալուց (եթե վաճառողի կողմից նախատեսված է)։</li>
|
||||
<li>Visa, MasterCard, МИР բանկային քարտեր,</li>
|
||||
<li>Արագ վճարումների համակարգ (СБП),</li>
|
||||
<li>էլեկտրոնային դրամապանակներ` YooMoney, QIWI,</li>
|
||||
<li>կանխիկ վճարում ստացման պահին, եթե դա նախատեսված է վաճառողի կողմից։</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="faq-item">
|
||||
<h3>Երբ կգրանցվեն գումարը քարտից։</h3>
|
||||
<p>Գործարքը կատարվում է անմիջապես, սակայն գումարը ժամանակավորապես սառեցվում է մինչև ապրանքը ստանանք։ Ստացումը հաստատելուց հետո գումարը ֆոխանցվում է վաճառողին։</p>
|
||||
<h3>Ե՞րբ է գումարը գանձվում քարտից։</h3>
|
||||
<p>Գործարքը կատարվում է անմիջապես, սակայն գումարը ժամանակավորապես պահվում է մինչև ապրանքի ստացումը հաստատվի։ Ստացումը հաստատվելուց հետո գումարը փոխանցվում է վաճառողին։</p>
|
||||
</div>
|
||||
|
||||
<div class="faq-item">
|
||||
<h3>Ինչու կարող է վճարումս մերժվել։</h3>
|
||||
<p>Մերժման հնարավոր պատճառները՝</p>
|
||||
<h3>Ինչո՞ւ կարող է վճարումը մերժվել։</h3>
|
||||
<p>Մերժման հնարավոր պատճառներն են`</p>
|
||||
<ul>
|
||||
<li>Հաշվին անբավարար միջոցներ,</li>
|
||||
<li>Քարտի գործառնությունների սահմանափակման գերազանցում,</li>
|
||||
<li>Քարտը արգելափակված է բանկի կողմից,</li>
|
||||
<li>Տեխնիկական խնդիրներ։</li>
|
||||
<li>հաշվում անբավարար միջոցներ,</li>
|
||||
<li>քարտի գործարքների սահմանաչափի գերազանցում,</li>
|
||||
<li>քարտի արգելափակում բանկի կողմից,</li>
|
||||
<li>տեխնիկական խափանումներ։</li>
|
||||
</ul>
|
||||
<p>Խորհուրդ ենք տալիս դիմել բանկ մանրամասների ճշտելման համար։</p>
|
||||
<p>Խորհուրդ ենք տալիս մանրամասները ճշտելու համար դիմել ձեր բանկին։</p>
|
||||
</div>
|
||||
|
||||
<div class="faq-item">
|
||||
<h3>Կստանամ վճարման անդրութ։</h3>
|
||||
<p>Այո, էլեկտրոնային անդրագիրը կուգա ձեր նշված էլ. հասցեին հաջողված վճարմանից անմիջապես հետո՝ համաձայն Վ դաշնային օրենքի № 54-ԿԶ-ի պահանջներին։</p>
|
||||
<h3>Կստանա՞մ վճարման կտրոն։</h3>
|
||||
<p>Այո, հաջող վճարումից անմիջապես հետո ձեր նշած էլեկտրոնային հասցեին կուղարկվի էլեկտրոնային կտրոն` համաձայն Դաշնային օրենք թիվ 54-ФЗ-ի պահանջների։</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
@@ -88,46 +88,46 @@
|
||||
<h2>Առաքում 🚚</h2>
|
||||
|
||||
<div class="faq-item">
|
||||
<h3>Ինչ առաքման ծառայություններ կան։</h3>
|
||||
<p><strong>Թվային ապրանքներ՝</strong> DexarMarket հարթակն ավտոմատ կերպով ուղարկում է թվային ապրանքները (լիցենզիաներ, բանալիներ, վկայագրեր) ձեր էլ. հասցեին կամ անձնական հաշվին՝ վճարմանից անմիջապես հետո։</p>
|
||||
<p><strong>Նյութական ապրանքներ՝</strong> Վաճառողն ինքնուրույն աշխատում է առաքման ծառայությունների հետ՝</p>
|
||||
<h3>Ի՞նչ առաքման ծառայություններ են օգտագործվում։</h3>
|
||||
<p><strong>Թվային ապրանքներ՝</strong> DexarMarket հարթակն ավտոմատ կերպով ուղարկում է թվային ապրանքները (լիցենզիաներ, բանալիներ, վկայագրեր) ձեր էլեկտրոնային հասցեին կամ անձնական հաշվին` վճարումը հաստատվելուց անմիջապես հետո։</p>
|
||||
<p><strong>Նյութական ապրանքներ՝</strong> Վաճառողն ինքնուրույն աշխատում է առաքման ծառայությունների հետ, այդ թվում`</p>
|
||||
<ul>
|
||||
<li>ՍԴԷԿ,</li>
|
||||
<li>Ռուսաստանի փոստ,</li>
|
||||
<li>СДЭК,</li>
|
||||
<li>Почта России,</li>
|
||||
<li>Boxberry,</li>
|
||||
<li>DPD,</li>
|
||||
<li>Yandex.Առաքում։</li>
|
||||
<li>Yandex.Доставка։</li>
|
||||
</ul>
|
||||
<p>Նյութական ապրանքների առաքման եղանակը ընտրվում է վաճառողի նախապատվություններին և նպատակակետին համապատասխան։</p>
|
||||
<p>Նյութական ապրանքների առաքման եղանակը ընտրվում է վաճառողի առաջարկների և առաքման ուղղության հիման վրա։</p>
|
||||
</div>
|
||||
|
||||
<div class="faq-item">
|
||||
<h3>Ինչքան արժե առաքումը։</h3>
|
||||
<p><strong>Թվային ապրանքներ՝</strong> Առաքումն անվճար է — ապրանքը կհասնի էլ. հասցեին անմիջապես։</p>
|
||||
<p><strong>Նյութական ապրանքներ՝</strong> Գինը որոշվում է վաճառողի կողմից և կախված է ապրանքի քաշից, չափսերից, առաքման եղանակից և տարածաշրջանից։ Վերջնական արժեքը ցուցադրվում է պատվերի ձևակերպման ժամանակ։</p>
|
||||
<h3>Որքա՞ն արժե առաքումը։</h3>
|
||||
<p><strong>Թվային ապրանքներ՝</strong> առաքումն անվճար է, և ապրանքը հասնում է էլեկտրոնային հասցեին գրեթե անմիջապես։</p>
|
||||
<p><strong>Նյութական ապրանքներ՝</strong> արժեքը որոշվում է վաճառողի կողմից և կախված է ապրանքի քաշից, չափերից, ընտրված առաքման եղանակից և տարածաշրջանից։ Վերջնական արժեքը ցուցադրվում է պատվերի ձևակերպման պահին։</p>
|
||||
</div>
|
||||
|
||||
<div class="faq-item">
|
||||
<h3>Ինչքան ժամանակ է առաքումը։</h3>
|
||||
<p><strong>Թվային ապրանքներ՝</strong> Ակնթարծիկ առաքում էլ. հասցեին (վճարումից հետո մի քանի րոպեի ընթացքում)։</p>
|
||||
<h3>Որքա՞ն ժամանակ է տևում առաքումը։</h3>
|
||||
<p><strong>Թվային ապրանքներ՝</strong> ակնթարթային առաքում էլեկտրոնային հասցեին (վճարումից հետո մի քանի րոպեի ընթացքում)։</p>
|
||||
<p><strong>Նյութական ապրանքներ</strong> (մոտավոր ժամկետներ)՝</p>
|
||||
<ul>
|
||||
<li>ՍԴԷԿ՝ 2–7 աշխատանքային օր,</li>
|
||||
<li>Ռուսաստանի փոստ՝ 5–14 աշխատանքային օր,</li>
|
||||
<li>Boxberry՝ 2–5 աշխատանքային օր,</li>
|
||||
<li>DPD՝ 1–3 աշխատանքային օր,</li>
|
||||
<li>Yandex.Առաքում՝ նույն օրը (եթե ձեր քաղաքում հասանելի է)։</li>
|
||||
<li>СДЭК` 2-7 աշխատանքային օր,</li>
|
||||
<li>Почта России` 5-14 աշխատանքային օր,</li>
|
||||
<li>Boxberry` 2-5 աշխատանքային օր,</li>
|
||||
<li>DPD` 1-3 աշխատանքային օր,</li>
|
||||
<li>Yandex.Доставка` նույն օրը, եթե ծառայությունը հասանելի է ձեր քաղաքում։</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="faq-item">
|
||||
<h3>Ինչպես հետևել ծանրուկը։</h3>
|
||||
<p>Դուք կստանաք հետևման կոդը ձեր էլ. հասցեին և կկարողանաք տեսնել պատվերի կարգավիճակը անձնական հաշվում։ Հետևել ծանրուկը կարելի է ընտրված սուրհանդակային ծառայության պաշտոնական կայքում։</p>
|
||||
<h3>Ինչպե՞ս հետևել առաքմանը։</h3>
|
||||
<p>Դուք էլեկտրոնային փոստով կստանաք հետևման կոդը և կկարողանաք պատվերի կարգավիճակը տեսնել անձնական հաշվում։ Առաքմանը կարելի է հետևել ընտրված ծառայության պաշտոնական կայքում։</p>
|
||||
</div>
|
||||
|
||||
<div class="faq-item">
|
||||
<h3>Ինչ անել, եթե ապրանքը եկել է վնասված։ ⛑</h3>
|
||||
<p>Ստուգեք ապրանքը սուրհանդակի ներկայությամբ։ Թերություններ հայտնաբերելու դեպքում կազմեք ընդունման մերժման ակտ և անհապաղ տեղեկացրեք վաճառողին և աջակցության ծառայությանը։</p>
|
||||
<h3>Ի՞նչ անել, եթե ապրանքը վնասված է հասել։ ⛑</h3>
|
||||
<p>Ստուգեք ապրանքը սուրհանդակի ներկայությամբ։ Եթե հայտնաբերվեն թերություններ, կազմեք ընդունումից հրաժարվելու ակտ և անմիջապես տեղեկացրեք վաճառողին ու աջակցության ծառայությանը։</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
@@ -135,27 +135,27 @@
|
||||
<h2>Վերադարձ և փոխանակում ✅</h2>
|
||||
|
||||
<div class="faq-item">
|
||||
<h3>Կարելի։ է վերադարձնել ապրանքը։</h3>
|
||||
<p>Այո, օրենքը թույլ է տալիս վերադարձնել որակյալ ապրանքը 7 օրվա ընթացքում։ Թերությունով ապրանքները վերադարձվում են հատուկ կանոններով։</p>
|
||||
<h3>Կարելի՞ է վերադարձնել ապրանքը։</h3>
|
||||
<p>Այո, օրենքը թույլ է տալիս վերադարձնել պատշաճ որակի ապրանքը 7 օրվա ընթացքում։ Թերություն ունեցող ապրանքների վերադարձը կարգավորվում է առանձին կանոններով։</p>
|
||||
</div>
|
||||
|
||||
<div class="faq-item">
|
||||
<h3>Ինչ ապրանքներ հնարավոր չէ վերադարձնել։</h3>
|
||||
<p>ՌԴ Կառավարության որոշման № 2463-ով նշված ապրանքները հնարավոր չէ վերադարձնել՝ դեղամիջոցներ, կոսմետիկա, ներքնակի սպիտակեղեն, ակտիվացված թվային ապրանքներ և անհատական պատվերներ։ Մանրամասները տեսեք <a [routerLink]="'/return-policy' | langRoute">«Վերադարձի քաղաքականություն»</a> բաժնում։</p>
|
||||
<h3>Ի՞նչ ապրանքներ հնարավոր չէ վերադարձնել։</h3>
|
||||
<p>ՌԴ Կառավարության թիվ 2463 որոշմամբ սահմանված ապրանքները վերադարձման ենթակա չեն. օրինակ` դեղամիջոցներ, կոսմետիկա, ներքնազգեստ, ակտիվացված թվային ապրանքներ և անհատական պատվերներ։ Մանրամասները տեսեք <a [routerLink]="'/return-policy' | langRoute">«Վերադարձի քաղաքականություն»</a> բաժնում։</p>
|
||||
</div>
|
||||
|
||||
<div class="faq-item">
|
||||
<h3>Ինչպես վերադարձնել գումարը։</h3>
|
||||
<h3>Ինչպե՞ս վերադարձնել գումարը։</h3>
|
||||
<p>
|
||||
1. Տեղեկացրեք վաճառողին ապրանքը վերադարձնելու մասին։<br>
|
||||
2. Վերադարձրեք ապրանքը սկզբնական փաթեթավորման մեջ։<br>
|
||||
3. Վաճառողը կստուգի ապրանքի վիճակը և կվերադարձնի գումարը նույն վճարման եղանակով (մինչև 30 օր սպասման ժամկետ)։
|
||||
1. Տեղեկացրեք վաճառողին ապրանքը վերադարձնելու մտադրության մասին։<br>
|
||||
2. Վերադարձրեք ապրանքը սկզբնական փաթեթավորմամբ։<br>
|
||||
3. Վաճառողը կստուգի ապրանքի վիճակը և գումարը կվերադարձնի նույն վճարման եղանակով (վերադարձը կարող է տևել մինչև 30 օր)։
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="faq-item">
|
||||
<h3>Ով կվճարի հետադարձի առաքումը։</h3>
|
||||
<p>Գնորդը վճարում է որակյալ ապրանքի հետադարձի առաքումը։ Թերություն հայտնաբերելու դեպքում ծախսերը կրում է վաճառողը։</p>
|
||||
<h3>Ո՞վ է վճարում հետադարձ առաքման համար։</h3>
|
||||
<p>Պատշաճ որակի ապրանքի հետադարձ առաքման ծախսերը կրում է գնորդը։ Եթե հայտնաբերվել է թերություն, ծախսերը կրում է վաճառողը։</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
@@ -163,18 +163,18 @@
|
||||
<h2>Երաշխիք 🔧</h2>
|
||||
|
||||
<div class="faq-item">
|
||||
<h3>Կա։ երաշխիք ապրանքների համար։</h3>
|
||||
<p>Մեր ապրանքների մեծ մասը ունի արտադրողի պաշտոնական երաշխիք։ Պայմանագիրը տատանվում է 12-ից 36 ամիս և նշված է յուրաքանչյուր ապրանքի էջում։</p>
|
||||
<h3>Կա՞ երաշխիք ապրանքների համար։</h3>
|
||||
<p>Ապրանքների մեծ մասի համար գործում է արտադրողի պաշտոնական երաշխիք։ Ժամկետը սովորաբար 12-ից 36 ամիս է և նշված է յուրաքանչյուր ապրանքի էջում։</p>
|
||||
</div>
|
||||
|
||||
<div class="faq-item">
|
||||
<h3>Ինչպես օգտվել երաշխիքով։</h3>
|
||||
<p>Տեղեկացրեք վաճառողին թերության մասին՝ կցելով թերությունների լուսանկարներ և երաշխիքային տալոն։ Վաճառողը կզբաղվի վերանորոգմամբ կամ ապրանքի փոխարինումով։</p>
|
||||
<h3>Ինչպե՞ս օգտվել երաշխիքից։</h3>
|
||||
<p>Տեղեկացրեք վաճառողին թերության մասին` կցելով լուսանկարներ և երաշխիքային կտրոնը։ Վաճառողը կկազմակերպի վերանորոգումը կամ ապրանքի փոխարինումը։</p>
|
||||
</div>
|
||||
|
||||
<div class="faq-item">
|
||||
<h3>Ինչը չի ընդգրկվում երաշխիքով։</h3>
|
||||
<p>Մեխանիկական վնասվածքներ, ոչ պատշաճ շահագործման հետևանքներ, ինքնակամ վերանորոգում, խոնավի ազդեցություն (եթե պաշտպանություն չկա), բնական մաշվածում — այս ամենը չի ընդգրկվում երաշխիքով։</p>
|
||||
<h3>Ի՞նչը չի մտնում երաշխիքի տակ։</h3>
|
||||
<p>Մեխանիկական վնասվածքները, ոչ պատշաճ շահագործման հետևանքները, ինքնուրույն վերանորոգումը, խոնավության ազդեցությունը (եթե պաշտպանություն նախատեսված չէ) և բնական մաշվածությունը երաշխիքային դեպք չեն համարվում։</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
@@ -182,18 +182,18 @@
|
||||
<h2>Անվտանգություն և գաղտնիություն 🔐</h2>
|
||||
|
||||
<div class="faq-item">
|
||||
<h3>Ինչպես եք պաշտպանում իմ անձնական տվյալները։</h3>
|
||||
<p>Մենք օգտագործում ենք SSL/TLS գաղտնագրման ժամանակակից մեթոդներ, չենք պահում քարտերի տվյալները և կատարում ենք № 152-ԿԶ դաշնային օրենքի պահանջները։ Մանրամասները — <a [routerLink]="'/privacy-policy' | langRoute">Գաղտնիության քաղաքականություն</a>ում։</p>
|
||||
<h3>Ինչպե՞ս եք պաշտպանում իմ անձնական տվյալները։</h3>
|
||||
<p>Մենք օգտագործում ենք SSL/TLS գաղտնագրման ժամանակակից մեթոդներ, չենք պահում քարտերի տվյալները և գործում ենք անձնական տվյալների պաշտպանության վերաբերյալ թիվ 152-ФЗ դաշնային օրենքի պահանջներին համապատասխան։ Մանրամասները կարող եք կարդալ <a [routerLink]="'/privacy-policy' | langRoute">Գաղտնիության քաղաքականություն</a> բաժնում։</p>
|
||||
</div>
|
||||
|
||||
<div class="faq-item">
|
||||
<h3>Ում է տրամադրվում իմ տվյալները։</h3>
|
||||
<p>Միայն ձեր վաճառողին՝ պատվերի մշակման և առաքման ծառայություններին։ Տվյալները չեն օգտագործվում երրորդ կողմերի կողմից շուկայական նպատակներով առանց ձեր թույլտվության։</p>
|
||||
<h3>Ու՞մ են տրամադրվում իմ տվյալները։</h3>
|
||||
<p>Տվյալները տրամադրվում են միայն ձեր վաճառողին և առաքման ծառայություններին` պատվերի մշակման և առաքման նպատակով։ Առանց ձեր թույլտվության դրանք չեն օգտագործվում երրորդ կողմերի կողմից մարքեթինգային նպատակներով։</p>
|
||||
</div>
|
||||
|
||||
<div class="faq-item">
|
||||
<h3>Ինչպես ջնջել հաշվիս։</h3>
|
||||
<p>Գրեք մեզ աջակցության ծառայություն՝ հաշվի ջնջման հայտով։ Հաշիվը կլիքվիդացվի անձնական տեղեկատվությամբ մեկ ամսվա ընթացքում։</p>
|
||||
<h3>Ինչպե՞ս ջնջել իմ հաշիվը։</h3>
|
||||
<p>Գրեք աջակցության ծառայությանը` հաշվի ջնջման հարցումով։ Հաշիվը և կից անձնական տվյալները կհեռացվեն մեկ ամսվա ընթացքում։</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
@@ -201,18 +201,18 @@
|
||||
<h2>Տեղեկատվություն վաճառողների համար 📋</h2>
|
||||
|
||||
<div class="faq-item">
|
||||
<h3>Ինչպես սկսել վաճառել հարթակում։</h3>
|
||||
<p>Մեր վաճառողներին միանալու համար դիմեք աջակցության ծառայությանը՝ էլեկտրոնային փոստով <a href="mailto:info@dexarmarket.ru">info@dexarmarket.ru</a>։</p>
|
||||
<h3>Ինչպե՞ս սկսել վաճառել հարթակում։</h3>
|
||||
<p>Հարթակում վաճառք սկսելու համար դիմեք աջակցության ծառայությանը` <a href="mailto:info@dexarmarket.ru">info@dexarmarket.ru</a> հասցեով։</p>
|
||||
</div>
|
||||
|
||||
<div class="faq-item">
|
||||
<h3>Ինչքան է հարթակի միջնորդավճարը։</h3>
|
||||
<p>Միջնորդավճարը կախված է ապրանքի տեսակից և վաճառքի ծավալից։ Ճիշտ պայմանները կարող եք իմանալ գրանցվելուց։</p>
|
||||
<h3>Որքա՞ն է հարթակի միջնորդավճարը։</h3>
|
||||
<p>Միջնորդավճարի չափը կախված է ապրանքի տեսակից և վաճառքի ծավալից։ Ճշգրիտ պայմանները կարող եք իմանալ գրանցվելուց հետո։</p>
|
||||
</div>
|
||||
|
||||
<div class="faq-item">
|
||||
<h3>Երբ կստանամ վաճառքի գումարը։</h3>
|
||||
<p>Վաճառողը ստանում է գումարը հաճախորդի կողմից ապրանքի ստացումը հաստատելուց հետո կամ առաքմանից երկու շաբաթ հետո, եթե հաճախորդը խնդիրներ չի նշել։</p>
|
||||
<h3>Ե՞րբ կստանամ վաճառքի գումարը։</h3>
|
||||
<p>Վաճառողը ստանում է գումարը հաճախորդի կողմից ապրանքի ստացումը հաստատելուց հետո կամ առաքումից երկու շաբաթ անց, եթե հաճախորդը որևէ խնդիր չի նշել։</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
@@ -220,25 +220,25 @@
|
||||
<h2>Աջակցության ծառայություն 💬</h2>
|
||||
|
||||
<div class="faq-item">
|
||||
<h3>Ինչպես կապվել աջակցության հետ։</h3>
|
||||
<h3>Ինչպե՞ս կապվել աջակցության հետ։</h3>
|
||||
<p>
|
||||
✉️ <strong>Էլ. հասցե՝</strong> <a href="mailto:info@dexarmarket.ru">info@dexarmarket.ru</a><br>
|
||||
📞 <strong>Հեռախոս (Ռուսաստան)՝</strong> <a href="tel:+79264593157">+7 (926) 459-31-57</a><br>
|
||||
📞 <strong>Հեռախոս (Հայաստան)՝</strong> <a href="tel:+37494861816">+374 94 86 18 16</a><br>
|
||||
🏢 <strong>Գրասենյակի աշխատանքային ժամերը՝</strong> 10:00—19:00 (ՄՍԿ)<br>
|
||||
🏢 <strong>Գրասենյակի աշխատանքային ժամերը՝</strong> 10:00-19:00 (ՄՍԿ)<br>
|
||||
❄️ <strong>Տեխնիկական աջակցությունը հասանելի է 24/7։</strong>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="faq-item">
|
||||
<h3>Ինչքան սպասել պատասխան։</h3>
|
||||
<p>Աշխատանքային օրերին պատասխանը գալիս է երկու ժամվա ընթացքում։ Տոներին և հանգստյան օրերին հնարավոր են ուշացումներ մինչև մեկ օր։</p>
|
||||
<h3>Որքա՞ն ժամանակում կստանամ պատասխան։</h3>
|
||||
<p>Աշխատանքային օրերին պատասխանը սովորաբար գալիս է երկու ժամվա ընթացքում։ Տոներին և հանգստյան օրերին հնարավոր են մինչև մեկ օրվա ուշացումներ։</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="legal-section">
|
||||
<h2>Օգնություն է հարկավոր։</h2>
|
||||
<p>Եթե լրացուցիչ հարցեր ունեք, դիմեք <a href="mailto:info@dexarmarket.ru">info@dexarmarket.ru</a> — մենք արագորեն կլուծենք ձեր հարցերը։</p>
|
||||
<h2>Օգնությո՞ւն է պետք։</h2>
|
||||
<p>Եթե լրացուցիչ հարցեր ունեք, գրեք <a href="mailto:info@dexarmarket.ru">info@dexarmarket.ru</a> հասցեին, և մենք հնարավորինս արագ կօգնենք ձեզ։</p>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,158 +1,158 @@
|
||||
<div class="legal-page">
|
||||
<div class="legal-container">
|
||||
<h1>Երաdelays 🔨</h1>
|
||||
<h1>Երաշխիք 🔨</h1>
|
||||
|
||||
<section class="legal-section">
|
||||
<h2>1. Երdelays հիմնական դրdelays</h2>
|
||||
<p>Սuis բadger սahmanumé DexarMarket մarketplace-ում գnumva apa­ranq­ne­ri eradiqayin caragayutyanneridek kargy.</p>
|
||||
<h2>1. Երաշխիքի հիմնական դրույթներ</h2>
|
||||
<p>Սույն բաժինը սահմանում է DexarMarket մարկետփլեյսում ձեռք բերված ապրանքների երաշխիքային սպասարկման կարգը։</p>
|
||||
<ul>
|
||||
<li>Eradiqayin partavorutyunnery katarumé apranqi Vacharoghn é, Rusastani orensdrutyun hamadzayn.</li>
|
||||
<li>DexarMarket hartakumé gortsumé miay orpes teghekatvakan mijnourd yev chi masnaktsumé eradiqayin paymanneri katarman.</li>
|
||||
<li>Eradiqayin baxverum é bazaraparén gortsaranayingortsaragnerov arajavordvats terutyyunnerin, vorvoné gnoghimatsu é.</li>
|
||||
<li>Երաշխիքային պարտավորությունները կատարում է հենց ապրանքի Վաճառողը` Ռուսաստանի Դաշնության օրենսդրությանը խիստ համապատասխան։</li>
|
||||
<li>DexarMarket հարթակը հանդես է գալիս միայն որպես տեղեկատվական միջնորդ և չի մասնակցում երաշխիքային պայմանների կատարմանը։</li>
|
||||
<li>Երաշխիքը տարածվում է բացառապես գործարանային թերությունների և այնպիսի անսարքությունների վրա, որոնք առաջացել չեն գնորդի մեղքով։</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section class="legal-section">
|
||||
<h2>2. Երашխdelays jamkety 🏷</h2>
|
||||
<p>Eradiqayin jamkety sahmanumy Vacharoghny kam artadroghny yev hratarakumé:</p>
|
||||
<h2>2. Երաշխիքային ժամկետ 🏷</h2>
|
||||
<p>Երաշխիքային ժամկետը սահմանվում է Վաճառողի կամ ապրանքի արտադրողի կողմից և հրապարակվում է.</p>
|
||||
<ul>
|
||||
<li>Mer kayqum apranqneri ejererum.</li>
|
||||
<li>Pakovkayin nerdy eradiqayin taloni mej.</li>
|
||||
<li>Apranqi uugheknogakan phastatgterum.</li>
|
||||
<li>Մեր կայքի ապրանքների էջերում։</li>
|
||||
<li>Փաթեթավորման մեջ ներառված երաշխիքային կտրոնում։</li>
|
||||
<li>Ապրանքին կցվող փաստաթղթերում։</li>
|
||||
</ul>
|
||||
|
||||
<p><strong>Apranqneri kategorianeri tipekan eradiqayin jamketneré:</strong></p>
|
||||
<p><strong>Երաշխիքային ժամկետների բնորոշ տևողությունը ըստ ապրանքային կատեգորիաների.</strong></p>
|
||||
<ul>
|
||||
<li><strong>Elektronika yev kentzaghayan tekhnika.</strong> 12-itz 24 amis.</li>
|
||||
<li><strong>Hamakargchayin tekhnika yev bakhichner.</strong> 12-itz 36 amis.</li>
|
||||
<li><strong>Hagust yev koshik.</strong> 30 or-itz 6 amis (kakhvats é seasonaynutyunitz).</li>
|
||||
<li><strong>Kahuyq.</strong> 12-itz 18 amis.</li>
|
||||
<li><strong>Tvayin artadrutyun.</strong> Ajakatsutyuny voroshum é Vacharoghny.</li>
|
||||
<li><strong>Էլեկտրոնիկա և կենցաղային տեխնիկա.</strong> 12-ից 24 ամիս։</li>
|
||||
<li><strong>Համակարգչային տեխնիկա և բաղադրիչներ.</strong> 12-ից 36 ամիս։</li>
|
||||
<li><strong>Հագուստ և կոշիկ.</strong> 30 օրից մինչև 6 ամիս` կախված սեզոնայնությունից։</li>
|
||||
<li><strong>Կահույք.</strong> 12-ից 18 ամիս։</li>
|
||||
<li><strong>Թվային արտադրանք.</strong> սպասարկման պայմանները սահմանում է Վաճառողը։</li>
|
||||
</ul>
|
||||
|
||||
<p>Eradiqayin jamkety sksbumé apranqy gnordi handzelou pahitz.</p>
|
||||
<p>Apranqi poxarinumy noratsutsumé eradiqayin jamkety poxarinmana tarmana pahitz.</p>
|
||||
<p>Yete eradiqayin jamkety nshanvats che Vacharoghkoghmitz, gnoghé iravunq uné nerkayayatsnel pahanjner 2 tari yntatsqum apranqi dzerkberumitz (RF «Sparoghnerineri iravunqneri pashtpanutyun» orenqi 19 hodvatsi hamalyatzq).</p>
|
||||
<p>Երաշխիքային ժամկետը հաշվարկվում է ապրանքը գնորդին հանձնելու պահից։</p>
|
||||
<p>Ապրանքի փոխարինման դեպքում երաշխիքային ժամկետը սկսվում է նորից` փոխարինման օրվանից։</p>
|
||||
<p>Եթե երաշխիքային ժամկետը Վաճառողի կողմից նշված չէ, գնորդն իրավունք ունի պահանջ ներկայացնել ապրանքը ձեռք բերելու օրվանից 2 տարվա ընթացքում` համաձայն ՌԴ «Սպառողների իրավունքների պաշտպանության մասին» օրենքի 19-րդ հոդվածի։</p>
|
||||
</section>
|
||||
|
||||
<section class="legal-section">
|
||||
<h2>3. Երashkhdelays paymanneré 📝</h2>
|
||||
<p>Eradiqayin gortsumé hetevyal pahanjneri katarman depqum:</p>
|
||||
<h2>3. Երաշխիքի տրամադրման պայմաններ 📝</h2>
|
||||
<p>Երաշխիքը գործում է հետևյալ պահանջների պահպանման դեպքում.</p>
|
||||
<ul>
|
||||
<li>Apranqi ogtagortsumy khist hamalyatzq tsutsumy.</li>
|
||||
<li>Inqnuruyn qandumé, norogy kam pokhakerpumé chi eghel.</li>
|
||||
<li>Artaqin irany yev nerqin tarrerri mekhanikan vnasvatsqner chkan.</li>
|
||||
<li>Bntakan plombnery yev sertiakany hamarneré pahhapanvats en (yete nakhatesvats en).</li>
|
||||
<li>Sarqy chi entarkvel bardzr jermasdijani, khonutyuny kam qimiakan niwterov.</li>
|
||||
<li>Eradiqayin talony yev gnman hastavatory (statsakan, hashiv) kan.</li>
|
||||
<li>Ապրանքը օգտագործվել է խստորեն ըստ հրահանգի։</li>
|
||||
<li>Չի կատարվել սարքի ինքնուրույն ապամոնտաժում, վերանորոգում կամ ձևափոխում։</li>
|
||||
<li>Բացակայում են արտաքին կորպուսի և ներքին տարրերի մեխանիկական վնասվածքները։</li>
|
||||
<li>Պահպանված են գործարանային պլոմբները և սերիական համարները (եթե դրանք նախատեսված են)։</li>
|
||||
<li>Սարքը չի ենթարկվել բարձր ջերմաստիճանի, խոնավության կամ քիմիական նյութերի ազդեցության։</li>
|
||||
<li>Առկա են երաշխիքային կտրոնը և գնման փաստը հաստատող փաստաթուղթը (կտրոն, անդորրագիր)։</li>
|
||||
</ul>
|
||||
|
||||
<p><strong>Eradiqayin dimumy anverhjar phastatgteré:</strong></p>
|
||||
<p><strong>Երաշխիքային դիմում ներկայացնելու համար անհրաժեշտ փաստաթղթեր.</strong></p>
|
||||
<ul>
|
||||
<li>Apranqn ir amboghakan komplektatsyayov.</li>
|
||||
<li>Eradiqayin talony (yete nerkayayatsvié).</li>
|
||||
<li>Gnman hasadatory phastatgter (statzakan, drantayin order).</li>
|
||||
<li>Apranqi tirapanji inqnuruthy havastichny phastatgter (orinaky antsnagiry).</li>
|
||||
<li>Ապրանքը` ամբողջական կոմպլեկտացիայով։</li>
|
||||
<li>Երաշխիքային կտրոնը (եթե առկա է)։</li>
|
||||
<li>Գնումը հաստատող փաստաթուղթ (կտրոն, դրամարկղային օրդեր)։</li>
|
||||
<li>Ապրանքի սեփականատիրոջ ինքնությունը հաստատող փաստաթուղթ (օրինակ` անձնագիր)։</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section class="legal-section">
|
||||
<h2>4. Երashkhdelays nórogy yev poxarinumy 🛠</h2>
|
||||
<h2>4. Երաշխիքային վերանորոգում և փոխարինում 🛠</h2>
|
||||
|
||||
<h3>Gnordi iravunqneré terutyun haytnaberelou depqum:</h3>
|
||||
<p>Yete terutyun haytnaberelié eradiqayin jamketum, duq iravunq unéq:</p>
|
||||
<h3>Գնորդի իրավունքները թերության հայտնաբերման դեպքում.</h3>
|
||||
<p>Եթե թերությունը հայտնաբերվել է երաշխիքային ժամկետի ընթացքում, դուք իրավունք ունեք.</p>
|
||||
<ul>
|
||||
<li>Andzradzchar veratsnogel ansparkutyuny.</li>
|
||||
<li>Stanalou nvazé apranq poxarinvoghiy.</li>
|
||||
<li>Pahanjel poxarinumy ayl apranqov arzhéqi verahashvarqov.</li>
|
||||
<li>Apranqi giny nshanatsel hamalyatsqy terutyuny.</li>
|
||||
<li>Veratartznel amboghakan gumaré apranqi hamar.</li>
|
||||
<li>Անվճար վերացնել անսարքությունը։</li>
|
||||
<li>Ստանալ անսարք ապրանքին համարժեք փոխարինող ապրանք։</li>
|
||||
<li>Պահանջել փոխարինում այլ ապրանքով` արժեքի համապատասխան վերահաշվարկով։</li>
|
||||
<li>Պահանջել ապրանքի գնի նվազեցում` թերությանը համամասնորեն։</li>
|
||||
<li>Ստանալ ապրանքի համար վճարված ամբողջ գումարի վերադարձ։</li>
|
||||
</ul>
|
||||
|
||||
<h3>Norogi jamketneré:</h3>
|
||||
<p>Norogy katarvumé arag, bayts aravelin jamketé kazmumé 45 or (RF «Sparoghnerineri iravunqneri pashtpanutyun» orenqi 20 hodvats). Yete jamketé khakhtvel é, karogh eq poxarinumy pahanjel kam gumaré veratartznel.</p>
|
||||
<h3>Վերանորոգման ժամկետներ.</h3>
|
||||
<p>Վերանորոգումն իրականացվում է հնարավորինս արագ, սակայն առավելագույն ժամկետը 45 օր է` համաձայն ՌԴ «Սպառողների իրավունքների պաշտպանության մասին» օրենքի 20-րդ հոդվածի։ Եթե այդ ժամկետը խախտվում է, դուք կարող եք պահանջել ապրանքի փոխարինում կամ գումարի վերադարձ։</p>
|
||||
|
||||
<h3>Zhamanakavory apranqi poxarinumy:</h3>
|
||||
<p>Yete norogman jamketé gerazantsum é mek shabatitz, vacharoghny partavory é trakan poxarinoghy tekhnikanatspes barbd apranqneri hamar.</p>
|
||||
<h3>Ապրանքի ժամանակավոր փոխարինում.</h3>
|
||||
<p>Եթե վերանորոգման ժամկետը գերազանցում է մեկ շաբաթը, վաճառողը պարտավոր է տեխնիկապես բարդ ապրանքների համար տրամադրել ժամանակավոր փոխարինող։</p>
|
||||
|
||||
<h3>Norogi hamar arakabumy:</h3>
|
||||
<p>Apranqy serverayin kentrón yev het haskatsutsuné katarumé vacharoghy kam mesnagitakan serverayin kentrony.</p>
|
||||
<h3>Առաքում վերանորոգման համար.</h3>
|
||||
<p>Ապրանքը սպասարկման կենտրոն տեղափոխելու և հետ վերադարձնելու ծախսերը կրում է վաճառողը կամ լիազորված սպասարկման կենտրոնը։</p>
|
||||
</section>
|
||||
|
||||
<section class="legal-section">
|
||||
<h2>5. Երashkhdelays chi gortsoghy depqeré 🔍</h2>
|
||||
<p>Eradiqayin chi gortsumé, yete haytnabervel en hetevyal hangamanqneré:</p>
|
||||
<h2>5. Դեպքեր, որոնք չեն մտնում երաշխիքի տակ 🔍</h2>
|
||||
<p>Երաշխիքը չի գործում, եթե հայտնաբերվել են հետևյալ հանգամանքները.</p>
|
||||
<ul>
|
||||
<li>Mekhanikan vnasvatsq (harkvatserov, ynknelov, charterov, kertsvatsqnerov);</li>
|
||||
<li>Ogtagortsman kanoanneri khakhtumy (skhaly miatsutsumy, tsanraberrnumy, ochstandard kirarukumy);</li>
|
||||
<li>Artaqin gortsónerov vnasvatsqner (heghuk, keghtotutyun, bardzr jermastijan, khonutyun);</li>
|
||||
<li>Inqnuruyn norogy (qandely, ardiakanatsutsuny, bakhichneri poxarinumy);</li>
|
||||
<li>Fors-mazhoryan hangamankner (hrdeh, hogheghats, goghnutyun, bunkakan aghety);</li>
|
||||
<li>Niwteri bntakan tserevekatsumy (guyni koruts, payliq, chnchik mashumy);</li>
|
||||
<li>Gortsaranayiny plombneri anuravortsi khakhtumy kam seriakan hamarneri vochnchatsnum.</li>
|
||||
<li>Մեխանիկական վնասվածք (հարվածներ, ընկնել, ճաքեր, քերծվածքներ),</li>
|
||||
<li>Օգտագործման կանոնների խախտում (սխալ միացում, գերաբեռնվածություն, ոչ ստանդարտ կիրառություն),</li>
|
||||
<li>Արտաքին գործոններից առաջացած վնասվածքներ (հեղուկ, կեղտ, բարձր ջերմաստիճան, խոնավություն),</li>
|
||||
<li>Ինքնուրույն վերանորոգում (ապամոնտաժում, արդիականացում, բաղադրիչների փոխարինում),</li>
|
||||
<li>Ֆորս-մաժորային հանգամանքներ (հրդեհ, հեղեղում, գողություն, բնական աղետներ),</li>
|
||||
<li>Նյութերի բնական մաշվածություն (գույնի կորուստ, փայլի նվազում, չնչին մաշվածություն),</li>
|
||||
<li>Գործարանային պլոմբների վնասում կամ սերիական համարների ոչնչացում։</li>
|
||||
</ul>
|
||||
|
||||
<p><strong>Nanapes eradiqayin depqer chen hamarvumé:</strong></p>
|
||||
<p><strong>Երաշխիքային դեպք չեն համարվում նաև.</strong></p>
|
||||
<ul>
|
||||
<li>Kosmetik terutyunner, voronq chi azdumé ashkhatanqin (makaretayin kertsvatsqner, phokr btsher);</li>
|
||||
<li>Artaqin teqi pokhutyanneré soveran ogtagortsman hetevanqov;</li>
|
||||
<li>Tsragvayin khndirner, voronq arrajatsumé eghel yets ardag tsragvayin apahovelov;</li>
|
||||
<li>Hamateghakanutyuny khndirner ayl artadroghneri sarqerov kam targatshkhayin apahovelov.</li>
|
||||
<li>Կոսմետիկ թերությունները, որոնք չեն ազդում աշխատանքի վրա (մակերեսային քերծվածքներ, փոքր բծեր),</li>
|
||||
<li>Արտաքին տեսքի փոփոխությունները սովորական օգտագործման հետևանքով,</li>
|
||||
<li>Ծրագրային խնդիրները, որոնք առաջացել են երրորդ կողմի ծրագրային ապահովման տեղադրման հետևանքով,</li>
|
||||
<li>Այլ արտադրողների սարքերի կամ ծրագրերի հետ համատեղելիության խնդիրները։</li>
|
||||
</ul>
|
||||
|
||||
<p>Eradiqayin sahmanapakumy tsakhsayin niwterov (marzanocner, lampichkaner, filtrner) arrandzhnahatuk nshanvats é apranqi nkaragrutyunum.</p>
|
||||
<p>Սպառվող նյութերի (մարտկոցներ, լամպեր, ֆիլտրեր) նկատմամբ երաշխիքային սահմանափակումները առանձին նշվում են ապրանքի նկարագրության մեջ։</p>
|
||||
</section>
|
||||
|
||||
<section class="legal-section">
|
||||
<h2>6. Երashkhdelays caragayutyanyits ogtvelu kargy 🗒</h2>
|
||||
<p>Eradiqayin caragayutyunitz ogtvelou hamar katareq hetevyal qaylerë:</p>
|
||||
<h2>6. Երաշխիքային սպասարկման դիմում ներկայացնելու կարգ 🗒</h2>
|
||||
<p>Երաշխիքային սպասարկումից օգտվելու համար կատարեք հետևյալ քայլերը.</p>
|
||||
<ol>
|
||||
<li>Kapvéq vacharoghyin dzert patverumy nvazamya teghekatvakan tvalnerov.</li>
|
||||
<li>Bajareq khndiry yev ktsveq lousankarner kam tesanyut (anhradzesht depqum).</li>
|
||||
<li>Vacharoghitz stanatsëq tsutsumy serverayin kentrón dimelou kam apranqy ugharkelou hastsen.</li>
|
||||
<li>Apranqy haratsreq serverin gnman hasdadoghy phastatgtoghy (eradiqayin talón, statzakan).</li>
|
||||
<li>Stanatsëq apranqi yndunman akty nórogi jamketi nshanakov.</li>
|
||||
<li>Veratserëq noroghvats apranqy nórogi avartman mahovy tzanuchatsumitz heto.</li>
|
||||
<li>Կապ հաստատեք վաճառողի հետ` օգտագործելով ձեր պատվերում նշված կոնտակտային տվյալները։</li>
|
||||
<li>Նկարագրեք խնդիրը և անհրաժեշտության դեպքում կցեք լուսանկարներ կամ տեսանյութ։</li>
|
||||
<li>Ստացեք վաճառողից հրահանգներ` ինչպես դիմել սպասարկման կենտրոն կամ որ հասցեով ուղարկել ապրանքը։</li>
|
||||
<li>Ապրանքը հանձնեք սպասարկման կենտրոն` գնման փաստը հաստատող փաստաթղթերով (երաշխիքային կտրոն, կտրոն)։</li>
|
||||
<li>Ստացեք ընդունման ակտ` վերանորոգման ժամկետի նշումով։</li>
|
||||
<li>Վերցրեք վերանորոգված ապրանքը` վերանորոգման ավարտի մասին ծանուցում ստանալուց հետո։</li>
|
||||
</ol>
|
||||
|
||||
<h3>Apranqy poshtov kam surhandakátsov urargelu kanonerë:</h3>
|
||||
<h3>Ապրանքը փոստով կամ սուրհանդակով ուղարկելու կանոններ.</h3>
|
||||
<ul>
|
||||
<li>Hushteloren pakovéq sarqy, khandarelov hnavary teghapahdman yntatsqum.</li>
|
||||
<li>Gnman phastatgteri patejennery yev khndri manramasn nkaragrutyuny teghadreq pakovkayi mej.</li>
|
||||
<li>Poshtayin arakuln dzevakeq gnahatman arzhéqov.</li>
|
||||
<li>Anverphayanorén pahéq trek hamary berny hetsevelou hamar.</li>
|
||||
<li>Սարքը հուսալի փաթեթավորեք` փոխադրման ընթացքում հնարավոր վնասները կանխելու համար։</li>
|
||||
<li>Փաթեթի մեջ դրեք գնման փաստաթղթերի պատճենները և խնդրի մանրամասն նկարագրությունը։</li>
|
||||
<li>Փոստային առաքումը ձևակերպեք հայտարարագրված արժեքով։</li>
|
||||
<li>Անպայման պահպանեք հետևման համարը` առաքման տեղաշարժը վերահսկելու համար։</li>
|
||||
</ul>
|
||||
|
||||
<p>Yete dzhvaroutyunner arrajanan, gnoghneré nanapes karogh en dimél mer ajakatsutyuny caragayutyunh tsovazgin email-ov: <a href="mailto:info@dexarmarket.ru">info@dexarmarket.ru</a>:</p>
|
||||
<p>Եթե դժվարություններ առաջանան, գնորդները կարող են նաև դիմել մեր աջակցման ծառայությանը էլեկտրոնային հասցեով` <a href="mailto:info@dexarmarket.ru">info@dexarmarket.ru</a>։</p>
|
||||
</section>
|
||||
|
||||
<section class="legal-section">
|
||||
<h2>7. Gnordi havélyal iravunqneré 🎯</h2>
|
||||
<p>Yete apranqy uné lrjakan terutyun, duq iravunq unéq:</p>
|
||||
<h2>7. Գնորդի լրացուցիչ իրավունքներ 🎯</h2>
|
||||
<p>Եթե ապրանքն ունի էական թերություն, դուք իրավունք ունեք.</p>
|
||||
<ul>
|
||||
<li>Pahanjel amboghakan gumaré veratartznel.</li>
|
||||
<li>Khndrél poxarinumy ayl modeli apranqov hamatéghakan arzhéqi verahashvarqov.</li>
|
||||
<li>Պահանջել ամբողջ գումարի վերադարձ։</li>
|
||||
<li>Պահանջել փոխարինում այլ մոդելի ապրանքով` արժեքի համապատասխան վերահաշվարկով։</li>
|
||||
</ul>
|
||||
|
||||
<p><strong>Lrjakan terutyun</strong> — dra depqy, yerb:</p>
|
||||
<p><strong>Էական թերություն</strong> է համարվում այն իրավիճակը, երբ.</p>
|
||||
<ul>
|
||||
<li>Hanchagy hnararvor ché véaratsnel.</li>
|
||||
<li>Hanchagy veratsneli hamar petq en mets tsakhser kam yerkar zhamanak.</li>
|
||||
<li>Terutyuny noritz arrajanum é norogi heto.</li>
|
||||
<li>Nwazé khndiry arrajanum é bazmakirats angam.</li>
|
||||
<li>Անսարքությունը հնարավոր չէ վերացնել։</li>
|
||||
<li>Անսարքության վերացումը պահանջում է մեծ ծախսեր կամ երկար ժամանակ։</li>
|
||||
<li>Թերությունը նորից է ի հայտ գալիս վերանորոգումից հետո։</li>
|
||||
<li>Նույն խնդիրը բազմիցս կրկնվում է։</li>
|
||||
</ul>
|
||||
|
||||
<p>Batsidranits, duq karogh eq hatahatél anvorak apranqi vacharqov arrajatsats vnasnery.</p>
|
||||
<p>Բացի այդ, դուք կարող եք պահանջել փոխհատուցել ոչ որակյալ ապրանքի վաճառքի հետևանքով առաջացած վնասները։</p>
|
||||
</section>
|
||||
|
||||
<section class="legal-section">
|
||||
<h2>8. Kapí teghekatvutyun 📞</h2>
|
||||
<p>Eradiqayin caragayutyuny veraberyal tsankatsats harts hamar nakh dimëq vacharoghyin (teseq apranqi ejerë kam dzert arakulin masin tzanuchatsumë).</p>
|
||||
<h2>8. Կոնտակտային տվյալներ 📞</h2>
|
||||
<p>Երաշխիքային սպասարկման հետ կապված ցանկացած հարցով նախ դիմեք վաճառողին (տես ապրանքի էջը կամ առաքման մասին ձեր ծանուցումը)։</p>
|
||||
|
||||
<p><strong>Yete vech luselu anhradzeshtutyun arrajatsav:</strong></p>
|
||||
<p>Uraréq email Marketplace-in: <a href="mailto:info@dexarmarket.ru">info@dexarmarket.ru</a> temayov «Eradiqayin harts — Patver №[patver hamary]»:</p>
|
||||
<p><strong>Եթե անհրաժեշտ է լուծել վեճը.</strong></p>
|
||||
<p>Ուղարկեք նամակ Մարկետփլեյսի էլեկտրոնային հասցեին` <a href="mailto:info@dexarmarket.ru">info@dexarmarket.ru</a>` թեմայում նշելով. «Երաշխիքային հարց — Պատվեր №[պատվերի համար]»։</p>
|
||||
|
||||
<p>Yete vacharoghy hrajarkvumé yndunelou pahanjy, duq iravunq unéq nakhadzernél apranqi vorakin ankakh phortsagrutyun yev datakan haylts nerkayayatsnel.</p>
|
||||
<p>Եթե վաճառողը հրաժարվում է ընդունել պահանջը, դուք իրավունք ունեք նախաձեռնել ապրանքի որակի անկախ փորձաքննություն և հայց ներկայացնել դատարան։</p>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -82,12 +82,12 @@
|
||||
<div class="novo-price-block">
|
||||
@if (item()!.discount > 0) {
|
||||
<div class="price-row">
|
||||
<span class="old-price">{{ item()!.price }} {{ item()!.currency }}</span>
|
||||
<span class="old-price">{{ effectivePrice() }} {{ effectiveCurrency() }}</span>
|
||||
<span class="discount-badge">-{{ item()!.discount }}%</span>
|
||||
</div>
|
||||
<div class="current-price">{{ getDiscountedPrice() | number:'1.2-2' }} {{ item()!.currency }}</div>
|
||||
<div class="current-price">{{ getDiscountedPrice() | number:'1.2-2' }} {{ effectiveCurrency() }}</div>
|
||||
} @else {
|
||||
<div class="current-price">{{ item()!.price }} {{ item()!.currency }}</div>
|
||||
<div class="current-price">{{ effectivePrice() }} {{ effectiveCurrency() }}</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
@@ -97,23 +97,37 @@
|
||||
<span class="dot"></span>
|
||||
{{ getStockLabel() }}
|
||||
</div>
|
||||
@if (item()!.quantity != null) {
|
||||
<span class="stock-qty">({{ item()!.quantity }} шт.)</span>
|
||||
@if (effectiveRemaining() != null) {
|
||||
<span class="stock-qty">({{ effectiveRemaining() }} шт.)</span>
|
||||
}
|
||||
</div>
|
||||
|
||||
@if (item()!.colour || item()!.size) {
|
||||
@if (availableColours().length || availableSizes().length || item()!.colour || (item()!.size && item()!.size!.toLowerCase() !== 'default')) {
|
||||
<div class="novo-variants">
|
||||
@if (item()!.colour) {
|
||||
@if (availableColours().length) {
|
||||
<div class="variant-group">
|
||||
<span class="variant-label">{{ 'itemDetail.colour' | translate }}:</span>
|
||||
<span class="variant-chip colour-chip">{{ item()!.colour }}</span>
|
||||
@for (c of availableColours(); track c) {
|
||||
<span class="colour-swatch" [class.active]="selectedColour() === c" [style.background-color]="c" [title]="c" (click)="selectColour(c)"></span>
|
||||
}
|
||||
</div>
|
||||
} @else if (item()!.colour) {
|
||||
<div class="variant-group">
|
||||
<span class="variant-label">{{ 'itemDetail.colour' | translate }}:</span>
|
||||
<span class="colour-swatch active" [style.background-color]="item()!.colour" [title]="item()!.colour"></span>
|
||||
</div>
|
||||
}
|
||||
@if (item()!.size) {
|
||||
@if (availableSizes().length) {
|
||||
<div class="variant-group">
|
||||
<span class="variant-label">{{ 'itemDetail.size' | translate }}:</span>
|
||||
<span class="variant-chip size-chip">{{ item()!.size }}</span>
|
||||
@for (s of availableSizes(); track s) {
|
||||
<span class="variant-chip size-chip" [class.active]="selectedSize() === s" (click)="selectSize(s)">{{ s }}</span>
|
||||
}
|
||||
</div>
|
||||
} @else if (item()!.size && item()!.size!.toLowerCase() !== 'default') {
|
||||
<div class="variant-group">
|
||||
<span class="variant-label">{{ 'itemDetail.size' | translate }}:</span>
|
||||
<span class="variant-chip size-chip active">{{ item()!.size }}</span>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
@@ -347,12 +361,12 @@
|
||||
<div class="dx-price-block">
|
||||
@if (item()!.discount > 0) {
|
||||
<div class="dx-price-row">
|
||||
<span class="dx-old-price">{{ item()!.price }} {{ item()!.currency }}</span>
|
||||
<span class="dx-old-price">{{ effectivePrice() }} {{ effectiveCurrency() }}</span>
|
||||
<span class="dx-discount-tag">-{{ item()!.discount }}%</span>
|
||||
</div>
|
||||
}
|
||||
<div class="dx-current-price">
|
||||
{{ item()!.discount > 0 ? (getDiscountedPrice() | number:'1.2-2') : item()!.price }} {{ item()!.currency }}
|
||||
{{ item()!.discount > 0 ? (getDiscountedPrice() | number:'1.2-2') : effectivePrice() }} {{ effectiveCurrency() }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -362,23 +376,37 @@
|
||||
<span class="dx-stock-dot"></span>
|
||||
{{ getStockLabel() }}
|
||||
</span>
|
||||
@if (item()!.quantity != null) {
|
||||
<span class="dx-stock-qty">({{ item()!.quantity }} шт.)</span>
|
||||
@if (effectiveRemaining() != null) {
|
||||
<span class="dx-stock-qty">({{ effectiveRemaining() }} шт.)</span>
|
||||
}
|
||||
</div>
|
||||
|
||||
@if (item()!.colour || item()!.size) {
|
||||
@if (availableColours().length || availableSizes().length || item()!.colour || (item()!.size && item()!.size!.toLowerCase() !== 'default')) {
|
||||
<div class="dx-variants">
|
||||
@if (item()!.colour) {
|
||||
@if (availableColours().length) {
|
||||
<div class="variant-group">
|
||||
<span class="variant-label">{{ 'itemDetail.colour' | translate }}:</span>
|
||||
<span class="variant-chip colour-chip">{{ item()!.colour }}</span>
|
||||
@for (c of availableColours(); track c) {
|
||||
<span class="colour-swatch" [class.active]="selectedColour() === c" [style.background-color]="c" [title]="c" (click)="selectColour(c)"></span>
|
||||
}
|
||||
</div>
|
||||
} @else if (item()!.colour) {
|
||||
<div class="variant-group">
|
||||
<span class="variant-label">{{ 'itemDetail.colour' | translate }}:</span>
|
||||
<span class="colour-swatch active" [style.background-color]="item()!.colour" [title]="item()!.colour"></span>
|
||||
</div>
|
||||
}
|
||||
@if (item()!.size) {
|
||||
@if (availableSizes().length) {
|
||||
<div class="variant-group">
|
||||
<span class="variant-label">{{ 'itemDetail.size' | translate }}:</span>
|
||||
<span class="variant-chip size-chip">{{ item()!.size }}</span>
|
||||
@for (s of availableSizes(); track s) {
|
||||
<span class="variant-chip size-chip" [class.active]="selectedSize() === s" (click)="selectSize(s)">{{ s }}</span>
|
||||
}
|
||||
</div>
|
||||
} @else if (item()!.size && item()!.size!.toLowerCase() !== 'default') {
|
||||
<div class="variant-group">
|
||||
<span class="variant-label">{{ 'itemDetail.size' | translate }}:</span>
|
||||
<span class="variant-chip size-chip active">{{ item()!.size }}</span>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
@@ -405,7 +433,8 @@
|
||||
</button>
|
||||
|
||||
<div class="dx-description">
|
||||
@if (getSimpleDescription()) {
|
||||
<!-- @if (getSimpleDescription()) { -->
|
||||
@if (false) {
|
||||
<p class="dx-simple-desc">{{ getSimpleDescription() }}</p>
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
// ========== DEXAR ITEM DETAIL - Redesigned 2026 ==========
|
||||
@use 'sass:color';
|
||||
|
||||
// ========== DEXAR ITEM DETAIL - Redesigned 2026 ==========
|
||||
$dx-font: "DM Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
|
||||
$dx-dark: #1e3c38;
|
||||
$dx-primary: #497671;
|
||||
@@ -50,7 +52,7 @@ $dx-card-bg: #f5f3f9;
|
||||
transition: all 0.2s;
|
||||
|
||||
&:hover {
|
||||
background: darken($dx-primary, 8%);
|
||||
background: color.adjust($dx-primary, $lightness: -8%);
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
}
|
||||
@@ -281,7 +283,7 @@ $dx-card-bg: #f5f3f9;
|
||||
box-shadow: 0 3px 4px 0 rgba(0, 0, 0, 0.15);
|
||||
|
||||
&:hover {
|
||||
background: darken($dx-primary, 8%);
|
||||
background: color.adjust($dx-primary, $lightness: -8%);
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 6px 16px rgba(73, 118, 113, 0.3);
|
||||
}
|
||||
@@ -294,7 +296,7 @@ $dx-card-bg: #f5f3f9;
|
||||
// Variant chips (colour/size) — shared between dexar and novo
|
||||
.dx-variants, .novo-variants {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
margin-bottom: 12px;
|
||||
|
||||
@@ -302,6 +304,7 @@ $dx-card-bg: #f5f3f9;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.variant-label {
|
||||
@@ -320,6 +323,37 @@ $dx-card-bg: #f5f3f9;
|
||||
border: 1.5px solid $dx-border;
|
||||
background: rgba(73, 118, 113, 0.06);
|
||||
color: $dx-primary;
|
||||
cursor: pointer;
|
||||
transition: background 0.15s, border-color 0.15s, box-shadow 0.15s;
|
||||
|
||||
&:hover {
|
||||
background: rgba(73, 118, 113, 0.12);
|
||||
}
|
||||
|
||||
&.active {
|
||||
border-color: $dx-primary;
|
||||
background: rgba(73, 118, 113, 0.18);
|
||||
box-shadow: 0 0 0 2px rgba(73, 118, 113, 0.25);
|
||||
}
|
||||
}
|
||||
|
||||
.colour-swatch {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
border-radius: 50%;
|
||||
border: 2px solid $dx-border;
|
||||
cursor: pointer;
|
||||
transition: border-color 0.15s, box-shadow 0.15s;
|
||||
flex-shrink: 0;
|
||||
|
||||
&:hover {
|
||||
border-color: $dx-primary;
|
||||
}
|
||||
|
||||
&.active {
|
||||
border-color: $dx-primary;
|
||||
box-shadow: 0 0 0 2px rgba(73, 118, 113, 0.25);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -492,7 +526,7 @@ $dx-card-bg: #f5f3f9;
|
||||
justify-content: center;
|
||||
|
||||
&:hover:not(:disabled) {
|
||||
background: darken($dx-primary, 8%);
|
||||
background: color.adjust($dx-primary, $lightness: -8%);
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import { Component, OnInit, OnDestroy, signal, ChangeDetectionStrategy, inject } from '@angular/core';
|
||||
import { Component, OnInit, OnDestroy, signal, computed, ChangeDetectionStrategy, inject } from '@angular/core';
|
||||
import { DecimalPipe } from '@angular/common';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
import { ActivatedRoute, RouterLink } from '@angular/router';
|
||||
import { ApiService, CartService, TelegramService, LanguageService, SeoService } from '../../services';
|
||||
import { Item, DescriptionField } from '../../models';
|
||||
import { AuthService } from '../../services/auth.service';
|
||||
import { Item, ItemDetail, DescriptionField } from '../../models';
|
||||
import { DomSanitizer, SafeHtml } from '@angular/platform-browser';
|
||||
import { Subscription } from 'rxjs';
|
||||
import { environment } from '../../../environments/environment';
|
||||
@@ -27,6 +28,55 @@ export class ItemDetailComponent implements OnInit, OnDestroy {
|
||||
error = signal<string | null>(null);
|
||||
isnovo = environment.theme === 'novo';
|
||||
|
||||
// Variant selection
|
||||
selectedColour = signal<string | null>(null);
|
||||
selectedSize = signal<string | null>(null);
|
||||
|
||||
availableColours = computed(() => {
|
||||
const details = this.item()?.itemDetails;
|
||||
if (!details?.length) return [] as string[];
|
||||
const unique = [...new Set(details.map(d => d.colour || d.color).filter((c): c is string => !!c))];
|
||||
return unique;
|
||||
});
|
||||
|
||||
availableSizes = computed(() => {
|
||||
const details = this.item()?.itemDetails;
|
||||
if (!details?.length) return [] as string[];
|
||||
// If a colour is selected, only show sizes available for that colour
|
||||
const colour = this.selectedColour();
|
||||
const filtered = colour
|
||||
? details.filter(d => (d.colour || d.color) === colour)
|
||||
: details;
|
||||
const unique = [...new Set(filtered.map(d => d.size).filter((s): s is string => !!s && s.toLowerCase() !== 'default'))];
|
||||
return unique;
|
||||
});
|
||||
|
||||
selectedDetail = computed<ItemDetail | null>(() => {
|
||||
const details = this.item()?.itemDetails;
|
||||
if (!details?.length) return null;
|
||||
const colour = this.selectedColour();
|
||||
const size = this.selectedSize();
|
||||
return details.find(d =>
|
||||
(!colour || (d.colour || d.color) === colour) &&
|
||||
(!size || d.size === size)
|
||||
) ?? null;
|
||||
});
|
||||
|
||||
effectivePrice = computed(() => {
|
||||
const detail = this.selectedDetail();
|
||||
return detail?.price ?? this.item()?.price ?? 0;
|
||||
});
|
||||
|
||||
effectiveCurrency = computed(() => {
|
||||
const detail = this.selectedDetail();
|
||||
return detail?.currency ?? this.item()?.currency ?? '';
|
||||
});
|
||||
|
||||
effectiveRemaining = computed(() => {
|
||||
const detail = this.selectedDetail();
|
||||
return detail?.remaining ?? this.item()?.quantity ?? null;
|
||||
});
|
||||
|
||||
newReview = {
|
||||
rating: 0,
|
||||
comment: '',
|
||||
@@ -42,6 +92,7 @@ export class ItemDetailComponent implements OnInit, OnDestroy {
|
||||
|
||||
private seoService = inject(SeoService);
|
||||
private i18n = inject(TranslateService);
|
||||
private authService = inject(AuthService);
|
||||
|
||||
constructor(
|
||||
private route: ActivatedRoute,
|
||||
@@ -73,6 +124,7 @@ export class ItemDetailComponent implements OnInit, OnDestroy {
|
||||
this.apiService.getItem(itemID).subscribe({
|
||||
next: (item) => {
|
||||
this.item.set(item);
|
||||
this.initVariantSelection(item);
|
||||
this.seoService.setItemMeta(item);
|
||||
this.loading.set(false);
|
||||
},
|
||||
@@ -84,6 +136,33 @@ export class ItemDetailComponent implements OnInit, OnDestroy {
|
||||
});
|
||||
}
|
||||
|
||||
private initVariantSelection(item: Item): void {
|
||||
// Auto-select the first available colour and size from itemDetails
|
||||
const details = item.itemDetails;
|
||||
if (details?.length) {
|
||||
const firstColour = details[0].colour || details[0].color || null;
|
||||
this.selectedColour.set(firstColour);
|
||||
const firstSize = details[0].size || null;
|
||||
this.selectedSize.set(firstSize);
|
||||
} else {
|
||||
this.selectedColour.set(item.colour ?? null);
|
||||
this.selectedSize.set(item.size ?? null);
|
||||
}
|
||||
}
|
||||
|
||||
selectColour(colour: string): void {
|
||||
this.selectedColour.set(colour);
|
||||
// If current size is not available for the new colour, reset to first available
|
||||
const sizes = this.availableSizes();
|
||||
if (sizes.length && this.selectedSize() && !sizes.includes(this.selectedSize()!)) {
|
||||
this.selectedSize.set(sizes[0]);
|
||||
}
|
||||
}
|
||||
|
||||
selectSize(size: string): void {
|
||||
this.selectedSize.set(size);
|
||||
}
|
||||
|
||||
selectPhoto(index: number): void {
|
||||
this.selectedPhotoIndex.set(index);
|
||||
}
|
||||
@@ -91,14 +170,21 @@ export class ItemDetailComponent implements OnInit, OnDestroy {
|
||||
addToCart(): void {
|
||||
const currentItem = this.item();
|
||||
if (currentItem) {
|
||||
this.cartService.addItem(currentItem.itemID);
|
||||
this.cartService.addItem(currentItem.itemID, 1, {
|
||||
colour: this.selectedColour() ?? undefined,
|
||||
size: this.selectedSize() ?? undefined,
|
||||
price: this.effectivePrice(),
|
||||
currency: this.effectiveCurrency()
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
getDiscountedPrice(): number {
|
||||
const currentItem = this.item();
|
||||
if (!currentItem) return 0;
|
||||
return getDiscountedPrice(currentItem);
|
||||
const price = this.effectivePrice();
|
||||
const discount = currentItem.discount || 0;
|
||||
return discount > 0 ? price * (1 - discount / 100) : price;
|
||||
}
|
||||
|
||||
// BackOffice integration helpers
|
||||
@@ -113,8 +199,7 @@ export class ItemDetailComponent implements OnInit, OnDestroy {
|
||||
getSimpleDescription(): string {
|
||||
const currentItem = this.item();
|
||||
if (!currentItem) return '';
|
||||
const lang = this.languageService.currentLanguage();
|
||||
return getTranslatedField(currentItem, 'simpleDescription', lang);
|
||||
return currentItem.simpleDescription || currentItem.description || '';
|
||||
}
|
||||
|
||||
hasDescriptionFields(): boolean {
|
||||
@@ -207,8 +292,7 @@ export class ItemDetailComponent implements OnInit, OnDestroy {
|
||||
itemID: currentItem.itemID,
|
||||
rating: this.newReview.rating,
|
||||
comment: this.newReview.comment.trim(),
|
||||
username: this.newReview.anonymous ? null : this.getUserDisplayName(),
|
||||
userId: this.telegramService.getUserId(),
|
||||
sessionID: this.authService.session()?.sessionId || '',
|
||||
timestamp: new Date().toISOString()
|
||||
};
|
||||
|
||||
|
||||
@@ -6,6 +6,10 @@
|
||||
<h2>Full Company Name</h2>
|
||||
<p>LIMITED LIABILITY COMPANY «INT FIN LOGISTIC»</p>
|
||||
<p><strong>Abbreviated name:</strong> LLC «INT FIN LOGISTIC»</p>
|
||||
<br>
|
||||
<p>LIMITED LIABILITY COMPANY «INT FACTORING»</p>
|
||||
<p><strong>Abbreviated name:</strong> LLC «INT FACTORING»</p>
|
||||
<p><strong>TIN:</strong> 9909697635</p>
|
||||
</section>
|
||||
|
||||
<section class="legal-section">
|
||||
|
||||
@@ -5,8 +5,10 @@
|
||||
<section class="legal-section">
|
||||
<h2>Կազմակերպության լիարժեկ անվանումը</h2>
|
||||
<p>ՍԱՀՄԱՆԱՓԱԿ ՊԱՏԱՍԽԱՆԱՏվությամբ Ընկերություն «ԻՆՏ ՖԻՆ ԼՈԳԻՍՏԻԿ»</p>
|
||||
<p><strong>Հապավոր անվանումը՝</strong> ՍՊԸ «ԻՆՏ ՖԻՆ ԼՈԳԻՍՏԻԿ»</p>
|
||||
</section>
|
||||
<p><strong>Հապավոր անվանումը՝</strong> ՍՊԸ «ԻՆՏ ՖԻՆ ԼՈԳԻՍՏԻԿ»</p> <br>
|
||||
<p>ՍԱՀՄԱՆԱՓԱԿ ՊԱՏԱՍԽԱՆԱՏվությամբ Ընկերություն «ԻՆՏ ՖԱԿՏՈՌԻՆԳ»</p>
|
||||
<p><strong>Հապավоր անվանումը՝</strong> ՍՊԸ «ԻՆՏ ՖԱԿՏՈՌԻՆԳ»</p>
|
||||
<p><strong>ՀՍՀ՝</strong> 9909697635</p> </section>
|
||||
|
||||
<section class="legal-section">
|
||||
<h2>Իրավաբանական հասցե</h2>
|
||||
|
||||
@@ -6,6 +6,10 @@
|
||||
<h2>Полное наименование организации</h2>
|
||||
<p>ОБЩЕСТВО С ОГРАНИЧЕННОЙ ОТВЕТСТВЕННОСТЬЮ «ИНТ ФИН ЛОГИСТИК»</p>
|
||||
<p><strong>Сокращенное наименование:</strong> ООО «ИНТ ФИН ЛОГИСТИК»</p>
|
||||
<br>
|
||||
<p>ОБЩЕСТВО С ОГРАНИЧЕННОЙ ОТВЕТСТВЕННОСТЬЮ «ИНТ ФАКТОРИНГ»</p>
|
||||
<p><strong>Сокращенное наименование:</strong> ООО «ИНТ ФАКТОРИНГ»</p>
|
||||
<p><strong>ИНН:</strong> 9909697635</p>
|
||||
</section>
|
||||
|
||||
<section class="legal-section">
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<section class="legal-section">
|
||||
<h2>1. GENERAL PROVISIONS</h2>
|
||||
|
||||
<p>1.1. This policy of LLC "INT FIN LOGISTIC" (TIN 9909697628), hereinafter referred to as the "Operator", describes the procedure for processing personal data and is aimed at protecting the rights and legitimate interests of data subjects. The document has been developed in accordance with Federal Law No. 152-FZ of July 27, 2006 "On Personal Data".</p>
|
||||
<p>1.1. This policy of LLC "INT FIN LOGISTIC" (TIN 9909697628) and LLC "INT FACTORING" (TIN 9909697635), hereinafter referred to as the "Operator", describes the procedure for processing personal data and is aimed at protecting the rights and legitimate interests of data subjects. The document has been developed in accordance with Federal Law No. 152-FZ of July 27, 2006 "On Personal Data".</p>
|
||||
|
||||
<p>1.2. The Policy defines the procedure and measures to ensure the security of personal data processing on the website <a href="https://dexarmarket.ru">https://dexarmarket.ru</a>, with the goal of protecting human and civil rights and freedoms, including the right to privacy, personal and family secrets.</p>
|
||||
|
||||
|
||||
@@ -1,367 +1,367 @@
|
||||
<div class="legal-page">
|
||||
<div class="legal-container">
|
||||
<h1>PERSONAL DATA PROCESSING POLICY</h1>
|
||||
<h1>ԱՆՁՆԱԿԱՆ ՏՎՅԱԼՆԵՐԻ ՄՇԱԿՄԱՆ ՔԱՂԱՔԱԿԱՆՈՒԹՅՈՒՆ</h1>
|
||||
|
||||
<section class="legal-section">
|
||||
<h2>1. GENERAL PROVISIONS</h2>
|
||||
<h2>1. ԸՆԴՀԱՆՈՒՐ ԴՐՈՒՅԹՆԵՐ</h2>
|
||||
|
||||
<p>1.1. This policy of LLC "INT FIN LOGISTIC" (TIN 9909697628), hereinafter referred to as the "Operator", describes the procedure for processing personal data and is aimed at protecting the rights and legitimate interests of data subjects. The document has been developed in accordance with Federal Law No. 152-FZ of July 27, 2006 "On Personal Data".</p>
|
||||
<p>1.1. «ԻՆՏ ՖԻՆ ԼՈՋԻՍՏԻԿ» ՍՊԸ-ի (ՀՎՀՀ 9909697628) և «ԻՆՏ ՖԱԿՏՈՐԻՆԳ» ՍՊԸ-ի (ՀՎՀՀ 9909697635), այսուհետ` «Օպերատոր», սույն քաղաքականությունը նկարագրում է անձնական տվյալների մշակման կարգը և ուղղված է տվյալների սուբյեկտների իրավունքների և օրինական շահերի պաշտպանությանը։ Փաստաթուղթը մշակվել է 2006 թվականի հուլիսի 27-ի «Անձնական տվյալների մասին» թիվ 152-ՖԶ դաշնային օրենքի համաձայն։</p>
|
||||
|
||||
<p>1.2. The Policy defines the procedure and measures to ensure the security of personal data processing on the website <a href="https://dexarmarket.ru">https://dexarmarket.ru</a>, with the goal of protecting human and civil rights and freedoms, including the right to privacy, personal and family secrets.</p>
|
||||
<p>1.2. Քաղաքականությունը սահմանում է <a href="https://dexarmarket.ru">https://dexarmarket.ru</a> կայքում անձնական տվյալների մշակման անվտանգության ապահովման կարգն ու միջոցները` մարդու և քաղաքացու իրավունքների և ազատությունների, այդ թվում` անձնական կյանքի, անձնական և ընտանեկան գաղտնիքի պաշտպանության նպատակով։</p>
|
||||
|
||||
<p>1.3. The document covers all processes carried out by the Operator relating to the processing of personal data.</p>
|
||||
<p>1.3. Փաստաթուղթը տարածվում է անձնական տվյալների մշակման հետ կապված բոլոր գործընթացների վրա, որոնք իրականացվում են Օպերատորի կողմից։</p>
|
||||
|
||||
<p>1.4. The Policy is mandatory for study and compliance by all persons authorized to process personal data.</p>
|
||||
<p>1.4. Քաղաքականությունը պարտադիր է ուսումնասիրելու և պահպանելու անձնական տվյալներ մշակելու իրավասություն ունեցող բոլոր անձանց համար։</p>
|
||||
|
||||
<p>1.5. It applies to all actions related to the processing of personal data on the website <a href="https://dexarmarket.ru">https://dexarmarket.ru</a> and in the Operator's information systems.</p>
|
||||
<p>1.5. Այն կիրառվում է <a href="https://dexarmarket.ru">https://dexarmarket.ru</a> կայքում և Օպերատորի տեղեկատվական համակարգերում անձնական տվյալների մշակման հետ կապված բոլոր գործողությունների նկատմամբ։</p>
|
||||
|
||||
<p>1.6. A User who places an order, opens a personal account, or otherwise interacts with the Operator expresses consent to the processing of their personal data in accordance with the Policy and the legislation of the Russian Federation. Continued use of the website indicates agreement with the provisions of the Policy. A User who is not willing to agree to the terms should refrain from using the resource.</p>
|
||||
<p>1.6. Օգտատերը, որը ձևակերպում է պատվեր, բացում է անձնական հաշիվ կամ այլ կերպ փոխգործակցում է Օպերատորի հետ, արտահայտում է համաձայնություն իր անձնական տվյալների մշակմանը` համաձայն սույն Քաղաքականության և Ռուսաստանի Դաշնության օրենսդրության։ Կայքի հետագա օգտագործումը նշանակում է համաձայնություն Քաղաքականության դրույթների հետ։ Այն Օգտատերը, որը պատրաստ չէ համաձայնել պայմաններին, պետք է ձեռնպահ մնա ռեսուրսից օգտվելուց։</p>
|
||||
|
||||
<p><strong>Additionally:</strong> This Policy applies to personal data collected both before and after the document comes into force.</p>
|
||||
<p><strong>Լրացուցիչ.</strong> Սույն Քաղաքականությունը տարածվում է անձնական տվյալների վրա, որոնք հավաքվել են ինչպես մինչև, այնպես էլ փաստաթղթի ուժի մեջ մտնելուց հետո։</p>
|
||||
</section>
|
||||
|
||||
<section class="legal-section">
|
||||
<h2>2. TERMS AND DEFINITIONS</h2>
|
||||
<h2>2. ՏԵՐՄԻՆՆԵՐ ԵՎ ՍԱՀՄԱՆՈՒՄՆԵՐ</h2>
|
||||
|
||||
<p>The following main terms and definitions are used in this Policy:</p>
|
||||
<p>Սույն Քաղաքականության մեջ օգտագործվում են հետևյալ հիմնական տերմիններն ու սահմանումները.</p>
|
||||
|
||||
<p><strong>Personal Data (PD)</strong> — any information directly or indirectly related to a specific individual (personal data subject).</p>
|
||||
<p><strong>Անձնական տվյալներ (ԱՏ)</strong> — ցանկացած տեղեկություն, որը ուղղակիորեն կամ անուղղակիորեն վերաբերում է որոշակի ֆիզիկական անձի (անձնական տվյալների սուբյեկտին)։</p>
|
||||
|
||||
<p><strong>Personal Data Information System (PDIS)</strong> — a set of personal data stored in databases, as well as technologies and means for their processing.</p>
|
||||
<p><strong>Անձնական տվյալների տեղեկատվական համակարգ (ԱՏՏՀ)</strong> — տվյալների բազաներում պահպանվող անձնական տվյալների ամբողջություն, ինչպես նաև դրանց մշակման տեխնոլոգիաներն ու միջոցները։</p>
|
||||
|
||||
<p><strong>Automated Processing of PD</strong> — data processing using computer means.</p>
|
||||
<p><strong>ԱՏ ավտոմատացված մշակում</strong> — տվյալների մշակում համակարգչային միջոցների կիրառմամբ։</p>
|
||||
|
||||
<p><strong>Blocking of PD</strong> — temporary suspension of data processing (except in cases of data clarification).</p>
|
||||
<p><strong>ԱՏ արգելափակում</strong> — տվյալների մշակման ժամանակավոր դադարեցում (բացառությամբ տվյալների ճշգրտման դեպքերի)։</p>
|
||||
|
||||
<p><strong>Depersonalization of PD</strong> — actions leading to the impossibility of determining the ownership of data to a specific person without additional information.</p>
|
||||
<p><strong>ԱՏ ապանձնավորում</strong> — գործողություններ, որոնց հետևանքով առանց լրացուցիչ տեղեկատվության անհնար է որոշել տվյալների պատկանելությունը կոնկրետ անձին։</p>
|
||||
|
||||
<p><strong>Internet Website (Website)</strong> — an automated information system available on the Internet at: <a href="https://dexarmarket.ru">https://dexarmarket.ru</a>.</p>
|
||||
<p><strong>Ինտերնետ կայք (Կայք)</strong> — ավտոմատացված տեղեկատվական համակարգ, որը հասանելի է ինտերնետում հետևյալ հասցեով` <a href="https://dexarmarket.ru">https://dexarmarket.ru</a>։</p>
|
||||
|
||||
<p><strong>Processing of PD</strong> — any actions with personal data, including collection, recording, storage, updating, use, transfer, destruction, and other operations.</p>
|
||||
<p><strong>ԱՏ մշակում</strong> — անձնական տվյալների հետ ցանկացած գործողություն, այդ թվում` հավաքագրում, գրանցում, պահպանում, թարմացում, օգտագործում, փոխանցում, ոչնչացում և այլ գործողություններ։</p>
|
||||
|
||||
<p><strong>Operator</strong> — a state or private body that independently or jointly organizes the processing of personal data.</p>
|
||||
<p><strong>Օպերատոր</strong> — պետական կամ մասնավոր մարմին, որը ինքնուրույն կամ համատեղ կազմակերպում է անձնական տվյալների մշակումը։</p>
|
||||
|
||||
<p><strong>Provision of PD</strong> — transfer of data to a specific person or group of persons.</p>
|
||||
<p><strong>ԱՏ տրամադրում</strong> — տվյալների փոխանցում կոնկրետ անձի կամ անձանց խմբի։</p>
|
||||
|
||||
<p><strong>Distribution of PD</strong> — disclosure of data to an indefinite number of persons, including publication in the media or on the Internet.</p>
|
||||
<p><strong>ԱՏ տարածում</strong> — տվյալների բացահայտում անորոշ թվով անձանց, այդ թվում` զանգվածային լրատվության միջոցներում կամ ինտերնետում հրապարակման միջոցով։</p>
|
||||
|
||||
<p><strong>Cross-border Transfer of PD</strong> — transfer of data to foreign authorities, companies, or individuals.</p>
|
||||
<p><strong>ԱՏ անդրսահմանային փոխանցում</strong> — տվյալների փոխանցում օտարերկրյա պետական մարմինների, ընկերությունների կամ ֆիզիկական անձանց։</p>
|
||||
|
||||
<p><strong>Destruction of PD</strong> — actions leading to the loss of the ability to recover data or destruction of material carriers.</p>
|
||||
<p><strong>ԱՏ ոչնչացում</strong> — գործողություններ, որոնք հանգեցնում են տվյալների վերականգնման հնարավորության կորստին կամ նյութական կրիչների ոչնչացմանը։</p>
|
||||
|
||||
<p><strong>PD Subject</strong> — an individual whose information is being processed.</p>
|
||||
<p><strong>ԱՏ սուբյեկտ</strong> — ֆիզիկական անձ, որի մասին տեղեկատվությունը մշակվում է։</p>
|
||||
|
||||
<p><strong>Confidentiality of PD</strong> — the Operator's obligation to protect data from distribution without the consent of the subject or a legal basis.</p>
|
||||
<p><strong>ԱՏ գաղտնիություն</strong> — Օպերատորի պարտավորությունը` պաշտպանել տվյալները տարածումից առանց սուբյեկտի համաձայնության կամ օրինական հիմքի։</p>
|
||||
|
||||
<p><strong>Seller (Contractor)</strong> — a person offering goods or services on the website <a href="https://dexarmarket.ru">https://dexarmarket.ru</a>.</p>
|
||||
<p><strong>Վաճառող (Կատարող)</strong> — անձ, որը <a href="https://dexarmarket.ru">https://dexarmarket.ru</a> կայքում առաջարկում է ապրանքներ կամ ծառայություններ։</p>
|
||||
|
||||
<p><strong>User</strong> — a person visiting or using resources managed by the Operator, including the website <a href="https://dexarmarket.ru">https://dexarmarket.ru</a>.</p>
|
||||
<p><strong>Օգտատեր</strong> — անձ, որը այցելում կամ օգտագործում է Օպերատորի կողմից կառավարվող ռեսուրսները, ներառյալ` <a href="https://dexarmarket.ru">https://dexarmarket.ru</a> կայքը։</p>
|
||||
|
||||
<p><strong>Order</strong> — an order for goods or services placed by the User on the website.</p>
|
||||
<p><strong>Պատվեր</strong> — Օգտատիրոջ կողմից կայքում ձևակերպված ապրանքների կամ ծառայությունների պատվեր։</p>
|
||||
|
||||
<p><strong>Cookies</strong> — small files saved on the user's device to remember preferences and actions during subsequent visits to the website.</p>
|
||||
<p><strong>Cookie-ներ</strong> — օգտատիրոջ սարքում պահպանվող փոքր ֆայլեր, որոնք օգտագործվում են նախընտրությունները և գործողությունները հիշելու համար կայք հետագա այցելությունների ընթացքում։</p>
|
||||
</section>
|
||||
|
||||
<section class="legal-section">
|
||||
<h2>3. LEGAL GROUNDS FOR PERSONAL DATA PROCESSING</h2>
|
||||
<h2>3. ԱՆՁՆԱԿԱՆ ՏՎՅԱԼՆԵՐԻ ՄՇԱԿՄԱՆ ԻՐԱՎԱԿԱՆ ՀԻՄՔԵՐԸ</h2>
|
||||
|
||||
<p>3.1. The legal basis for PD Processing, depending on the purposes of the process involving PD Processing, may be:</p>
|
||||
<p>3.1. ԱՏ մշակման իրավական հիմքը, կախված ԱՏ մշակման գործընթացի նպատակներից, կարող է լինել.</p>
|
||||
|
||||
<h3>3.1.1. The Constitution of the Russian Federation, as well as a set of legal acts:</h3>
|
||||
<h3>3.1.1. Ռուսաստանի Դաշնության Սահմանադրությունը, ինչպես նաև իրավական ակտերի ամբողջությունը.</h3>
|
||||
<ul>
|
||||
<li>Tax Code of the Russian Federation;</li>
|
||||
<li>Civil Code of the Russian Federation;</li>
|
||||
<li>Articles 86–90 of the Labor Code of the Russian Federation;</li>
|
||||
<li>Federal Law No. 115-FZ of August 7, 2001 "On Countering the Legalization (Laundering) of Proceeds of Crime and the Financing of Terrorism";</li>
|
||||
<li>Federal Law No. 152-FZ of July 27, 2006 "On Personal Data";</li>
|
||||
<li>Federal Law No. 39-FZ of April 22, 1996 "On the Securities Market";</li>
|
||||
<li>Federal Law No. 208-FZ of December 26, 1995 "On Joint-Stock Companies";</li>
|
||||
<li>Federal Law No. 149-FZ of July 27, 2006 "On Information, Information Technologies and the Protection of Information";</li>
|
||||
<li>Federal Law No. 27-FZ of April 1, 1996 "On Individual (Personified) Accounting in the Mandatory Pension Insurance System";</li>
|
||||
<li>Federal Law No. 63-FZ of April 6, 2011 "On Electronic Signatures";</li>
|
||||
<li>Federal Law No. 402-FZ of December 6, 2011 "On Accounting";</li>
|
||||
<li>Federal Law No. 161-FZ of June 27, 2011 "On the National Payment System";</li>
|
||||
<li>Decree of the Government of the Russian Federation No. 687 of September 15, 2008 "On Approval of the Regulation on the Specifics of Personal Data Processing Carried Out Without the Use of Automation";</li>
|
||||
<li>Decree of the Government of the Russian Federation No. 1119 of November 1, 2012 "On Approval of the Requirements for the Protection of Personal Data During Their Processing in Personal Data Information Systems";</li>
|
||||
<li>other regulatory legal acts of the Russian Federation and regulatory documents of executive authorities.</li>
|
||||
<li>Ռուսաստանի Դաշնության հարկային օրենսգիրք,</li>
|
||||
<li>Ռուսաստանի Դաշնության քաղաքացիական օրենսգիրք,</li>
|
||||
<li>Ռուսաստանի Դաշնության աշխատանքային օրենսգրքի 86-90-րդ հոդվածներ,</li>
|
||||
<li>2001 թվականի օգոստոսի 7-ի «Հանցավոր ճանապարհով ստացված եկամուտների օրինականացման (լվացման) և ահաբեկչության ֆինանսավորման դեմ պայքարի մասին» թիվ 115-ՖԶ դաշնային օրենք,</li>
|
||||
<li>2006 թվականի հուլիսի 27-ի «Անձնական տվյալների մասին» թիվ 152-ՖԶ դաշնային օրենք,</li>
|
||||
<li>1996 թվականի ապրիլի 22-ի «Արժեթղթերի շուկայի մասին» թիվ 39-ՖԶ դաշնային օրենք,</li>
|
||||
<li>1995 թվականի դեկտեմբերի 26-ի «Բաժնետիրական ընկերությունների մասին» թիվ 208-ՖԶ դաշնային օրենք,</li>
|
||||
<li>2006 թվականի հուլիսի 27-ի «Տեղեկատվության, տեղեկատվական տեխնոլոգիաների և տեղեկատվության պաշտպանության մասին» թիվ 149-ՖԶ դաշնային օրենք,</li>
|
||||
<li>1996 թվականի ապրիլի 1-ի «Պարտադիր կենսաթոշակային ապահովագրության համակարգում անհատական (անձնավորված) հաշվառման մասին» թիվ 27-ՖԶ դաշնային օրենք,</li>
|
||||
<li>2011 թվականի ապրիլի 6-ի «Էլեկտրոնային ստորագրության մասին» թիվ 63-ՖԶ դաշնային օրենք,</li>
|
||||
<li>2011 թվականի դեկտեմբերի 6-ի «Հաշվապահական հաշվառման մասին» թիվ 402-ՖԶ դաշնային օրենք,</li>
|
||||
<li>2011 թվականի հունիսի 27-ի «Ազգային վճարային համակարգի մասին» թիվ 161-ՖԶ դաշնային օրենք,</li>
|
||||
<li>2008 թվականի սեպտեմբերի 15-ի Ռուսաստանի Դաշնության կառավարության թիվ 687 որոշում «Անձնական տվյալների մշակման առանձնահատկությունների մասին կանոնակարգը հաստատելու մասին, երբ մշակումն իրականացվում է առանց ավտոմատացման միջոցների օգտագործման»,</li>
|
||||
<li>2012 թվականի նոյեմբերի 1-ի Ռուսաստանի Դաշնության կառավարության թիվ 1119 որոշում «Անձնական տվյալների տեղեկատվական համակարգերում դրանց մշակման ընթացքում անձնական տվյալների պաշտպանության պահանջները հաստատելու մասին»,</li>
|
||||
<li>Ռուսաստանի Դաշնության այլ նորմատիվ իրավական ակտեր և գործադիր մարմինների նորմատիվ փաստաթղթեր։</li>
|
||||
</ul>
|
||||
|
||||
<p>3.1.2. The Operator's Charter.</p>
|
||||
<p>3.1.2. Օպերատորի կանոնադրությունը։</p>
|
||||
|
||||
<p>3.1.3. Contracts concluded between the Operator and the Personal Data Subject, including in cases where the Operator exercises its right to assign rights (claims) under such contracts, between the Operator and another person who has entrusted the Operator with PD Processing, as well as for the conclusion of contracts of which Personal Data Subjects are parties.</p>
|
||||
<p>3.1.3. Օպերատորի և Անձնական տվյալների սուբյեկտի միջև կնքված պայմանագրերը, ներառյալ դեպքերը, երբ Օպերատորն իրականացնում է նման պայմանագրերից բխող իրավունքների (պահանջների) զիջման իր իրավունքը, Օպերատորի և այլ անձի միջև, որը Օպերատորին հանձնարարել է ԱՏ մշակումը, ինչպես նաև պայմանագրերի կնքման համար, որոնց կողմ են հանդիսանում Անձնական տվյալների սուբյեկտները։</p>
|
||||
|
||||
<p>3.1.4. Consent to PD Processing (in cases not directly provided for by the legislation of the Russian Federation, but corresponding to the Operator's powers), including the consent of applicants for vacant positions to PD Processing, the consent of interns to PD Processing, the consent of employees to PD Processing; the consent of clients to PD Processing, the consent of Users of the relevant Website, the consent of other Personal Data Subjects.</p>
|
||||
<p>3.1.4. ԱՏ մշակման համաձայնությունը (այն դեպքերում, որոնք ուղղակիորեն նախատեսված չեն Ռուսաստանի Դաշնության օրենսդրությամբ, բայց համապատասխանում են Օպերատորի լիազորություններին), ներառյալ թափուր հաստիքների թեկնածուների համաձայնությունը ԱՏ մշակմանը, պրակտիկանտների համաձայնությունը ԱՏ մշակմանը, աշխատակիցների համաձայնությունը ԱՏ մշակմանը, հաճախորդների համաձայնությունը ԱՏ մշակմանը, համապատասխան Կայքի Օգտատերերի համաձայնությունը, ինչպես նաև այլ Անձնական տվյալների սուբյեկտների համաձայնությունը։</p>
|
||||
|
||||
<p>3.1.5. A contract between the operator and a third party, in which the latter entrusts the Operator with the processing of personal data of the Personal Data Subject or transfers personal data of the Personal Data Subject on the basis of a concluded contract.</p>
|
||||
<p>3.1.5. Օպերատորի և երրորդ անձի միջև պայմանագիր, որով վերջինս Օպերատորին հանձնարարում է Անձնական տվյալների սուբյեկտի անձնական տվյալների մշակումը կամ փոխանցում է Անձնական տվյալների սուբյեկտի անձնական տվյալները կնքված պայմանագրի հիման վրա։</p>
|
||||
</section>
|
||||
|
||||
<section class="legal-section">
|
||||
<h2>4. CATEGORIES OF PERSONAL DATA SUBJECTS WHOSE PERSONAL DATA IS PROCESSED BY THE OPERATOR</h2>
|
||||
<h2>4. ԱՆՁՆԱԿԱՆ ՏՎՅԱԼՆԵՐԻ ՍՈՒԲՅԵԿՏՆԵՐԻ ԿԱՏԵԳՈՐԻԱՆԵՐԸ, ՈՐՈՆՑ ՏՎՅԱԼՆԵՐԸ ՄՇԱԿՎՈՒՄ ԵՆ ՕՊԵՐԱՏՈՐԻ ԿՈՂՄԻՑ</h2>
|
||||
|
||||
<p>4.1. The Operator processes PD obtained in accordance with the law, belonging to:</p>
|
||||
<p>4.1. Օպերատորը մշակում է օրենքով ստացված ԱՏ, որոնք վերաբերում են.</p>
|
||||
<ul>
|
||||
<li>Job candidates and employees of the Operator;</li>
|
||||
<li>Former employees of the Operator;</li>
|
||||
<li>Close relatives/family members of the Operator's employees, interns;</li>
|
||||
<li>Potential clients, individual clients, individual entrepreneur clients (individuals registered in the established manner and carrying out entrepreneurial activities without forming a legal entity), individuals engaged in private practice in accordance with the legislation of the Russian Federation (self-employed), individual beneficiaries, beneficial owners, representatives;</li>
|
||||
<li>Individuals who have entered into civil law contracts with the Operator, including purchase and sale, for the provision of services and/or performance of work for the Operator;</li>
|
||||
<li>Users of the Operator's Websites, Order recipients (if the User has specified another person as the Order recipient);</li>
|
||||
<li>Clients of other legal entities, the Processing of Personal Data for which is carried out on behalf of the said legal entities in accordance with the legislation of the Russian Federation;</li>
|
||||
<li>Owners of the Operator;</li>
|
||||
<li>Other subjects who have entered or intend to enter into contractual relations with the Operator and/or who apply to the Operator with applications/appeals.</li>
|
||||
<li>Օպերատորի աշխատանքի թեկնածուներին և աշխատակիցներին,</li>
|
||||
<li>Օպերատորի նախկին աշխատակիցներին,</li>
|
||||
<li>Օպերատորի աշխատակիցների և պրակտիկանտների մերձավոր ազգականներին/ընտանիքի անդամներին,</li>
|
||||
<li>պոտենցիալ հաճախորդներին, ֆիզիկական անձ հաճախորդներին, անհատ ձեռնարկատեր հաճախորդներին (օրենքով սահմանված կարգով գրանցված և առանց իրավաբանական անձ ստեղծելու ձեռնարկատիրական գործունեություն իրականացնող ֆիզիկական անձանց), Ռուսաստանի Դաշնության օրենսդրության համաձայն մասնավոր պրակտիկայով զբաղվող ֆիզիկական անձանց (ինքնազբաղվածներ), անհատական շահառուներին, վերջնական շահառուներին, ներկայացուցիչներին,</li>
|
||||
<li>ֆիզիկական անձանց, որոնք Օպերատորի հետ կնքել են քաղաքացիաիրավական պայմանագրեր, այդ թվում` առուվաճառքի, ծառայությունների մատուցման և/կամ աշխատանքների կատարման պայմանագրեր Օպերատորի համար,</li>
|
||||
<li>Օպերատորի Կայքերի Օգտատերերին, Պատվերի ստացողներին (եթե Օգտատերը որպես Պատվերի ստացող նշել է այլ անձի),</li>
|
||||
<li>այլ իրավաբանական անձանց հաճախորդներին, որոնց անձնական տվյալների մշակումը կատարվում է նշված իրավաբանական անձանց հանձնարարությամբ` Ռուսաստանի Դաշնության օրենսդրությանը համապատասխան,</li>
|
||||
<li>Օպերատորի սեփականատերերին,</li>
|
||||
<li>այլ սուբյեկտներին, որոնք մտել են կամ մտադիր են մտնել պայմանագրային հարաբերությունների մեջ Օպերատորի հետ և/կամ դիմում են Օպերատորին դիմումներով/բողոքներով։</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section class="legal-section">
|
||||
<h2>5. CATEGORIES OF PERSONAL DATA PROCESSED BY THE OPERATOR</h2>
|
||||
<h2>5. ՕՊԵՐԱՏՈՐԻ ԿՈՂՄԻՑ ՄՇԱԿՎՈՂ ԱՆՁՆԱԿԱՆ ՏՎՅԱԼՆԵՐԻ ԿԱՏԵԳՈՐԻԱՆԵՐԸ</h2>
|
||||
|
||||
<p>5.1. The Operator processes the following categories of PD of Users and Order recipients:</p>
|
||||
<p>5.1. Օպերատորը մշակում է Օգտատերերի և Պատվերի ստացողների հետևյալ կատեգորիայի ԱՏ.</p>
|
||||
|
||||
<ul>
|
||||
<li>Information obtained during registration and/or placing an Order (surname, first name, actual address, phone number, email address, cookies);</li>
|
||||
<li>Information obtained during interaction with Users (surname, first name, patronymic, gender, place of birth, date of birth, passport data (series, number, issuing authority, department code, issue date, registration address), actual address, phone number, email address);</li>
|
||||
<li>Information about the Order delivery method, payment method and payment status, and if the final Order recipient differs from the User, also the surname, first name, patronymic, gender, place of birth, date of birth, passport data, delivery address, and phone number of the Order recipient;</li>
|
||||
<li>Information about User complaints (submitted by the User via the Websites or otherwise);</li>
|
||||
<li>Geolocation (location) information.</li>
|
||||
<li>գրանցման և/կամ Պատվերի ձևակերպման ընթացքում ստացված տեղեկատվություն (ազգանուն, անուն, փաստացի հասցե, հեռախոսահամար, էլեկտրոնային փոստի հասցե, cookie-ներ),</li>
|
||||
<li>Օգտատերերի հետ փոխգործակցության ընթացքում ստացված տեղեկատվություն (ազգանուն, անուն, հայրանուն, սեռ, ծննդավայր, ծննդյան ամսաթիվ, անձնագրային տվյալներ (սերիա, համար, տված մարմին, ստորաբաժանման կոդ, տրման ամսաթիվ, գրանցման հասցե), փաստացի հասցե, հեռախոսահամար, էլեկտրոնային փոստի հասցե),</li>
|
||||
<li>Պատվերի առաքման եղանակի, վճարման եղանակի և վճարման կարգավիճակի մասին տեղեկատվություն, և եթե Պատվերի վերջնական ստացողը տարբերվում է Օգտատիրոջից, ապա նաև Պատվերի ստացողի ազգանունը, անունը, հայրանունը, սեռը, ծննդավայրը, ծննդյան ամսաթիվը, անձնագրային տվյալները, առաքման հասցեն և հեռախոսահամարը,</li>
|
||||
<li>Օգտատերերի բողոքների մասին տեղեկատվություն (ներկայացված Կայքերի միջոցով կամ այլ եղանակով),</li>
|
||||
<li>աշխարհագրական տեղորոշման (լոկացիայի) տվյալներ։</li>
|
||||
</ul>
|
||||
|
||||
<p>5.2. The Operator processes the following categories of PD of Personal Data Subjects who contact the Operator with claims of alleged violation of their rights: surname, first name, actual address, contact information (phone number and/or email address) of the rights holder or other person whose right was allegedly violated, and/or the applicant, if acting as an authorized representative of the rights holder or other person whose right was allegedly violated, information about received claims, the progress and results of their consideration.</p>
|
||||
<p>5.2. Օպերատորը մշակում է այն Անձնական տվյալների սուբյեկտների հետևյալ կատեգորիայի ԱՏ, որոնք դիմում են Օպերատորին իրենց իրավունքների ենթադրյալ խախտման վերաբերյալ պահանջներով` իրավունքակալի կամ այլ անձի, որի իրավունքը ենթադրաբար խախտվել է, ինչպես նաև դիմողի ազգանուն, անուն, փաստացի հասցե, կոնտակտային տվյալներ (հեռախոսահամար և/կամ էլեկտրոնային փոստի հասցե), եթե դիմողը գործում է որպես իրավունքակալի կամ այլ անձի լիազորված ներկայացուցիչ, ում իրավունքը ենթադրաբար խախտվել է, ինչպես նաև ստացված պահանջների, դրանց քննության ընթացքի և արդյունքների վերաբերյալ տեղեկատվություն։</p>
|
||||
|
||||
<p>5.3. Personal data specified in the paragraphs of this section above may be obtained by the Operator in one of the following ways:</p>
|
||||
<p>5.3. Վերը նշված բաժնի կետերում նշված անձնական տվյալները Օպերատորի կողմից կարող են ստացվել հետևյալ եղանակներից մեկով.</p>
|
||||
<ul>
|
||||
<li>Provided by Personal Data Subjects by filling in the appropriate forms on one of the Websites, by sending correspondence or emails to the Operator's email addresses;</li>
|
||||
<li>Obtained from third parties in cases provided for in this section. In particular, Users' PD may be obtained by the Operator directly from Sellers or other counterparties of the Operator in connection with the execution of the Seller's instructions and/or the performance of other actions provided for by the current legislation of the Russian Federation.</li>
|
||||
<li>Անձնական տվյալների սուբյեկտների կողմից համապատասխան ձևաթղթերը լրացնելով Օպերատորի Կայքերից մեկում, նամակագրություն կամ էլեկտրոնային նամակներ ուղարկելով Օպերատորի էլեկտրոնային հասցեներին,</li>
|
||||
<li>երրորդ անձանցից ստացված` սույն բաժնով նախատեսված դեպքերում։ Մասնավորապես, Օգտատերերի ԱՏ կարող են Օպերատորի կողմից ստացվել անմիջապես Վաճառողներից կամ Օպերատորի այլ կոնտրագենտներից` Վաճառողի հանձնարարությունների կատարման և/կամ Ռուսաստանի Դաշնության գործող օրենսդրությամբ նախատեսված այլ գործողությունների իրականացման հետ կապված։</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section class="legal-section">
|
||||
<h2>6. PRINCIPLES, PROCEDURE AND CONDITIONS OF PERSONAL DATA PROCESSING</h2>
|
||||
<h2>6. ԱՆՁՆԱԿԱՆ ՏՎՅԱԼՆԵՐԻ ՄՇԱԿՄԱՆ ՍԿԶԲՈՒՆՔՆԵՐԸ, ԿԱՐԳԸ ԵՎ ՊԱՅՄԱՆՆԵՐԸ</h2>
|
||||
|
||||
<h3>6.1. Principles of Personal Data Processing</h3>
|
||||
<p>PD Processing by the Operator is carried out on the basis of the following principles:</p>
|
||||
<h3>6.1. Անձնական տվյալների մշակման սկզբունքները</h3>
|
||||
<p>Օպերատորի կողմից ԱՏ մշակումը իրականացվում է հետևյալ սկզբունքների հիման վրա.</p>
|
||||
<ul>
|
||||
<li>legality and fairness;</li>
|
||||
<li>limitation of PD Processing to the achievement of specific, predetermined and legitimate purposes;</li>
|
||||
<li>prevention of PD Processing incompatible with the purposes of PD collection;</li>
|
||||
<li>prevention of combining databases containing PD, the Processing of which is carried out for purposes incompatible with each other;</li>
|
||||
<li>Processing only such PD that correspond to the purposes of their Processing;</li>
|
||||
<li>compliance of the content and volume of Processed PD with the stated purposes of Processing;</li>
|
||||
<li>prevention of PD Processing that is excessive in relation to the stated purposes of their Processing;</li>
|
||||
<li>ensuring the accuracy, sufficiency and relevance of PD in relation to the purposes of PD Processing;</li>
|
||||
<li>storage of PD in a form that allows identifying the Personal Data Subject for no longer than required by the purposes of PD Processing;</li>
|
||||
<li>destruction or depersonalization of PD upon achieving the purposes of their Processing, upon withdrawal of consent to their Processing by the Personal Data Subject, or in the event of loss of the need to achieve these purposes.</li>
|
||||
<li>օրինականություն և բարեխղճություն,</li>
|
||||
<li>ԱՏ մշակման սահմանափակում միայն կոնկրետ, նախապես սահմանված և օրինական նպատակների հասնելու շրջանակներում,</li>
|
||||
<li>ԱՏ մշակման բացառումը, որը անհամատեղելի է ԱՏ հավաքագրման նպատակների հետ,</li>
|
||||
<li>տվյալների բազաների միավորումը չթույլատրելը, եթե դրանցում պարունակվող ԱՏ մշակվում են միմյանց հետ անհամատեղելի նպատակներով,</li>
|
||||
<li>մշակել միայն այնպիսի ԱՏ, որոնք համապատասխանում են դրանց մշակման նպատակներին,</li>
|
||||
<li>մշակվող ԱՏ բովանդակության և ծավալի համապատասխանությունը հայտարարված նպատակներին,</li>
|
||||
<li>չթույլատրել ԱՏ ավելորդ մշակում` դրանց մշակման հայտարարված նպատակների համեմատ,</li>
|
||||
<li>ԱՏ ճշգրտության, բավարարության և արդիականության ապահովում` ԱՏ մշակման նպատակների նկատմամբ,</li>
|
||||
<li>ԱՏ պահպանում այնպիսի ձևով, որը թույլ է տալիս նույնականացնել Անձնական տվյալների սուբյեկտին ոչ ավելի երկար, քան պահանջվում է ԱՏ մշակման նպատակներով,</li>
|
||||
<li>ԱՏ ոչնչացում կամ ապանձնավորում` դրանց մշակման նպատակներին հասնելուց հետո, ԱՏ սուբյեկտի կողմից դրանց մշակման համաձայնությունը հետ կանչելու դեպքում կամ այդ նպատակներին հասնելու անհրաժեշտության վերացման դեպքում։</li>
|
||||
</ul>
|
||||
|
||||
<h3>6.2. Obligations of the Operator's Employees</h3>
|
||||
<p>Employees of the Operator authorized to Process Personal Data are obliged to:</p>
|
||||
<h3>6.2. Օպերատորի աշխատակիցների պարտականությունները</h3>
|
||||
<p>Օպերատորի այն աշխատակիցները, որոնք լիազորված են մշակել Անձնական տվյալներ, պարտավոր են.</p>
|
||||
<ul>
|
||||
<li>Know and strictly comply with the provisions of the legislation of the Russian Federation in the field of PD;</li>
|
||||
<li>Know and comply with the provisions of this Policy;</li>
|
||||
<li>Know and comply with the Operator's local acts on PD Processing and security;</li>
|
||||
<li>Process PD only within the scope of their job duties;</li>
|
||||
<li>Not disclose PD processed by the Operator;</li>
|
||||
<li>Report actions of other persons that may lead to violation of the provisions of this Policy.</li>
|
||||
<li>իմանալ և խստորեն պահպանել Ռուսաստանի Դաշնության օրենսդրության դրույթները ԱՏ ոլորտում,</li>
|
||||
<li>իմանալ և պահպանել սույն Քաղաքականության դրույթները,</li>
|
||||
<li>իմանալ և պահպանել Օպերատորի տեղական ակտերը ԱՏ մշակման և անվտանգության վերաբերյալ,</li>
|
||||
<li>մշակել ԱՏ միայն իրենց ծառայողական պարտականությունների շրջանակում,</li>
|
||||
<li>չբացահայտել Օպերատորի կողմից մշակվող ԱՏ,</li>
|
||||
<li>տեղեկացնել այլ անձանց այնպիսի գործողությունների մասին, որոնք կարող են հանգեցնել սույն Քաղաքականության դրույթների խախտմանը։</li>
|
||||
</ul>
|
||||
|
||||
<p>6.3. The Operator is obliged to ensure that the Operator's employees who directly carry out the Processing of Personal Data are familiarized with the provisions of Russian legislation on Personal Data, including the requirements for PD protection, local acts on the Processing and protection of Personal Data, and training of the Operator's employees.</p>
|
||||
<p>6.3. Օպերատորը պարտավոր է ապահովել, որ իր այն աշխատակիցները, որոնք անմիջականորեն իրականացնում են Անձնական տվյալների մշակումը, ծանոթ լինեն Ռուսաստանի օրենսդրության դրույթներին անձնական տվյալների վերաբերյալ, ներառյալ` ԱՏ պաշտպանության պահանջներին, անձնական տվյալների մշակման և պաշտպանության վերաբերյալ տեղական ակտերին, ինչպես նաև ապահովել Օպերատորի աշխատակիցների վերապատրաստումը։</p>
|
||||
|
||||
<h3>6.4. Conditions for Personal Data Processing</h3>
|
||||
<p>The Operator processes PD if at least one of the following conditions is met:</p>
|
||||
<h3>6.4. Անձնական տվյալների մշակման պայմանները</h3>
|
||||
<p>Օպերատորը մշակում է ԱՏ, եթե բավարարվում է հետևյալ պայմաններից առնվազն մեկը.</p>
|
||||
<ul>
|
||||
<li>PD Processing is carried out with the consent of the PD Subject to the Processing of their PD;</li>
|
||||
<li>PD Processing is necessary to achieve the goals provided for by an international treaty of the Russian Federation or by law;</li>
|
||||
<li>PD Processing is necessary for the administration of justice, execution of a judicial act;</li>
|
||||
<li>PD Processing is necessary for the performance of a contract to which the PD Subject is a party, beneficiary, or guarantor;</li>
|
||||
<li>PD Processing is necessary for the exercise of the rights and legitimate interests of the Operator or third parties;</li>
|
||||
<li>Processing of PD to which the PD Subject has provided access to an unlimited number of persons is carried out;</li>
|
||||
<li>Processing of PD subject to publication or mandatory disclosure in accordance with FZ-152 is carried out.</li>
|
||||
<li>ԱՏ մշակումը իրականացվում է ԱՏ սուբյեկտի համաձայնությամբ իր ԱՏ մշակման վերաբերյալ,</li>
|
||||
<li>ԱՏ մշակումը անհրաժեշտ է Ռուսաստանի Դաշնության միջազգային պայմանագրով կամ օրենքով նախատեսված նպատակներին հասնելու համար,</li>
|
||||
<li>ԱՏ մշակումը անհրաժեշտ է արդարադատության իրականացման, դատական ակտի կատարման համար,</li>
|
||||
<li>ԱՏ մշակումը անհրաժեշտ է պայմանագրի կատարման համար, որի կողմ, շահառու կամ երաշխավոր է ԱՏ սուբյեկտը,</li>
|
||||
<li>ԱՏ մշակումը անհրաժեշտ է Օպերատորի կամ երրորդ անձանց իրավունքների և օրինական շահերի իրականացման համար,</li>
|
||||
<li>իրականացվում է այն ԱՏ մշակումը, որոնց նկատմամբ ԱՏ սուբյեկտը տրամադրել է հասանելիություն անսահմանափակ թվով անձանց,</li>
|
||||
<li>իրականացվում է այն ԱՏ մշակումը, որոնք ենթակա են հրապարակման կամ պարտադիր բացահայտման` թիվ 152-ՖԶ օրենքին համապատասխան։</li>
|
||||
</ul>
|
||||
|
||||
<p>6.5. The Operator carries out PD Processing using automated and non-automated means, including collection, recording, systematization, accumulation, storage, clarification (updating, modification), extraction, use, transfer (Distribution, Provision, access), Depersonalization, Blocking, deletion, Destruction of Personal Data within the timeframes necessary to achieve the purposes of Personal Data Processing.</p>
|
||||
<p>6.5. Օպերատորը իրականացնում է ԱՏ մշակում ավտոմատացված և ոչ ավտոմատացված միջոցներով, ներառյալ` անձնական տվյալների հավաքագրում, գրանցում, համակարգում, կուտակում, պահպանում, ճշգրտում (թարմացում, փոփոխություն), քաղում, օգտագործում, փոխանցում (տարածում, տրամադրում, հասանելիություն), ապանձնավորում, արգելափակում, ջնջում, ոչնչացում` այն ժամկետներում, որոնք անհրաժեշտ են անձնական տվյալների մշակման նպատակներին հասնելու համար։</p>
|
||||
|
||||
<p>6.6. The Operator is prohibited from making decisions based solely on the Automated Processing of Personal Data that produce legal consequences with respect to the Personal Data Subject, or otherwise affect their rights and legitimate interests, except in cases and conditions provided for by the legislation of the Russian Federation in the field of Personal Data.</p>
|
||||
<p>6.6. Օպերատորին արգելվում է կայացնել որոշումներ միայն Անձնական տվյալների ավտոմատացված մշակման հիման վրա, որոնք իրավական հետևանքներ են առաջացնում ԱՏ սուբյեկտի համար կամ այլ կերպ ազդում են նրա իրավունքների և օրինական շահերի վրա, բացառությամբ Ռուսաստանի Դաշնության օրենսդրությամբ նախատեսված դեպքերի և պայմանների։</p>
|
||||
|
||||
<p>6.7. Representatives of state authorities (including controlling, supervisory, law enforcement, inquiry, investigation, and other authorized bodies on grounds provided for by the current legislation of the Russian Federation) obtain access to PD Processed by the Operator in the scope and manner established by the legislation of the Russian Federation.</p>
|
||||
<p>6.7. Պետական մարմինների ներկայացուցիչները (ներառյալ վերահսկող, հսկողական, իրավապահ, հետաքննության, քննության և այլ լիազորված մարմինները` Ռուսաստանի Դաշնության գործող օրենսդրությամբ նախատեսված հիմքերով) ստանում են Օպերատորի կողմից մշակվող ԱՏ հասանելիություն` Ռուսաստանի Դաշնության օրենսդրությամբ սահմանված ծավալով և կարգով։</p>
|
||||
|
||||
<p>6.8. The Processing of Personal Data by the Operator is carried out with the consent of the Personal Data Subject, except in cases established by the legislation of the Russian Federation, in compliance with the requirements for PD Confidentiality established by Art. 7 of FZ-152, as well as the adoption of measures aimed at ensuring the fulfillment of obligations for the Processing and protection of Personal Data established by the legislation of the Russian Federation.</p>
|
||||
<p>6.8. Անձնական տվյալների մշակումը Օպերատորի կողմից իրականացվում է ԱՏ սուբյեկտի համաձայնությամբ, բացառությամբ Ռուսաստանի Դաշնության օրենսդրությամբ սահմանված դեպքերի, պահպանելով թիվ 152-ՖԶ օրենքի 7-րդ հոդվածով սահմանված ԱՏ գաղտնիության պահանջները, ինչպես նաև ընդունելով միջոցներ, որոնք ուղղված են Ռուսաստանի Դաշնության օրենսդրությամբ սահմանված պարտավորությունների կատարմանը` անձնական տվյալների մշակման և պաշտպանության մասով։</p>
|
||||
|
||||
<p>6.9. The condition for the termination of Personal Data Processing may be the achievement of Personal Data Processing purposes, the expiration of the consent of the Personal Data Subject to the Processing of their PD, or the withdrawal of consent by the Personal Data Subject to the Processing of their PD, as well as the identification of unlawful PD Processing.</p>
|
||||
<p>6.9. Անձնական տվյալների մշակման դադարեցման հիմք կարող է լինել անձնական տվյալների մշակման նպատակներին հասնելը, ԱՏ սուբյեկտի համաձայնության ժամկետի ավարտը իր ԱՏ մշակման վերաբերյալ կամ ԱՏ սուբյեկտի կողմից համաձայնության հետկանչը, ինչպես նաև ԱՏ ապօրինի մշակման փաստի հայտնաբերումը։</p>
|
||||
|
||||
<p>6.10. Personal Data is stored in a form that allows identifying the Personal Data Subject for no longer than required by the purposes of Personal Data Processing, except in cases where the storage period of Personal Data is established by FZ-152, a contract to which the Personal Data Subject is a party, beneficiary, or guarantor.</p>
|
||||
<p>6.10. Անձնական տվյալները պահպանվում են այնպիսի ձևով, որը թույլ է տալիս նույնականացնել Անձնական տվյալների սուբյեկտին ոչ ավելի երկար, քան պահանջվում է անձնական տվյալների մշակման նպատակներով, բացառությամբ այն դեպքերի, երբ ԱՏ պահպանման ժամկետը սահմանված է թիվ 152-ՖԶ օրենքով կամ պայմանագրով, որի կողմ, շահառու կամ երաշխավոր է ԱՏ սուբյեկտը։</p>
|
||||
|
||||
<p>6.11. In the event of confirmation of the fact of inaccuracy of Personal Data or unlawfulness of their Processing, the Personal Data is subject to updating by the Operator, and the Processing must be terminated, respectively.</p>
|
||||
<p>6.11. Եթե հաստատվում է անձնական տվյալների անճշտության կամ դրանց մշակման անօրինականության փաստը, ապա անձնական տվյալները ենթակա են թարմացման Օպերատորի կողմից, իսկ մշակումը` համապատասխանաբար դադարեցման։</p>
|
||||
|
||||
<p>6.12. The Operator does not verify and, as a rule, does not have the ability to verify the relevance and reliability of the information provided by Personal Data Subjects obtained through each of the Operator's Websites. The Operator assumes that Personal Data Subjects, acting reasonably and in good faith, provide reliable and sufficient PD and maintain them in an up-to-date state.</p>
|
||||
<p>6.12. Օպերատորը չի ստուգում և, որպես կանոն, հնարավորություն չունի ստուգելու իր Կայքերից յուրաքանչյուրի միջոցով Անձնական տվյալների սուբյեկտների կողմից տրամադրված տեղեկատվության արդիականությունն ու հավաստիությունը։ Օպերատորը ենթադրում է, որ Անձնական տվյալների սուբյեկտները, գործելով ողջամտորեն և բարեխղճորեն, տրամադրում են հավաստի և բավարար ԱՏ և պահպանում են դրանք արդիական վիճակում։</p>
|
||||
|
||||
<h3>6.13. Procedure for Obtaining Clarifications</h3>
|
||||
<p>The Operator provides the Personal Data Subject or their representative with information regarding the Processing of their Personal Data upon the appropriate request or inquiry of the Personal Data Subject or their representative in an accessible form.</p>
|
||||
<h3>6.13. Պարզաբանումներ ստանալու կարգը</h3>
|
||||
<p>Օպերատորը Անձնական տվյալների սուբյեկտին կամ նրա ներկայացուցչին տրամադրում է նրա անձնական տվյալների մշակման վերաբերյալ տեղեկատվություն` Անձնական տվյալների սուբյեկտի կամ նրա ներկայացուցչի համապատասխան դիմումի կամ հարցման դեպքում հասանելի ձևով։</p>
|
||||
|
||||
<p>6.14. The request of the Personal Data Subject for obtaining information regarding the Processing of their PD by the Operator must contain:</p>
|
||||
<p>6.14. Անձնական տվյալների սուբյեկտի հարցումը Օպերատորի կողմից իր ԱՏ մշակման վերաբերյալ տեղեկատվություն ստանալու համար պետք է պարունակի.</p>
|
||||
<ul>
|
||||
<li>surname, first name, phone number, email address, and actual residential address of the Personal Data Subject or their representative, and, in the case of a representative's inquiry, the details of the power of attorney or other document confirming the representative's authority;</li>
|
||||
<li>Information confirming the participation of the Personal Data Subject in relations with the Operator (contract number, contract date, etc.);</li>
|
||||
<li>Signature of the Personal Data Subject or their representative.</li>
|
||||
<li>Անձնական տվյալների սուբյեկտի կամ նրա ներկայացուցչի ազգանունը, անունը, հեռախոսահամարը, էլեկտրոնային փոստի հասցեն և փաստացի բնակության հասցեն, իսկ ներկայացուցչի դիմելու դեպքում` լիազորագիրը կամ ներկայացուցչի լիազորությունները հաստատող այլ փաստաթղթի տվյալները,</li>
|
||||
<li>տեղեկատվություն, որը հաստատում է Անձնական տվյալների սուբյեկտի մասնակցությունը Օպերատորի հետ հարաբերություններին (պայմանագրի համար, պայմանագրի ամսաթիվ և այլն),</li>
|
||||
<li>Անձնական տվյալների սուբյեկտի կամ նրա ներկայացուցչի ստորագրությունը։</li>
|
||||
</ul>
|
||||
|
||||
<p>6.15. The request may be sent in the form of an electronic document and signed with an electronic signature in accordance with the legislation of the Russian Federation.</p>
|
||||
<p>6.15. Հարցումը կարող է ուղարկվել էլեկտրոնային փաստաթղթի տեսքով և ստորագրվել էլեկտրոնային ստորագրությամբ` Ռուսաստանի Դաշնության օրենսդրությանը համապատասխան։</p>
|
||||
|
||||
<p>6.16. The appeal of the Personal Data Subject or their legal representative to the Operator for the purpose of exercising their rights established by FZ-152 is carried out in writing in the form established by the Operator or in free form at the Operator's registered address.</p>
|
||||
<p>6.16. Անձնական տվյալների սուբյեկտի կամ նրա օրինական ներկայացուցչի դիմումը Օպերատորին` իր իրավունքների իրականացման նպատակով, որոնք սահմանված են թիվ 152-ՖԶ օրենքով, կատարվում է գրավոր` Օպերատորի կողմից սահմանված ձևով կամ ազատ ձևով` Օպերատորի գրանցված հասցեով։</p>
|
||||
|
||||
<p>6.17. The Operator considers the appeal of the Personal Data Subject/withdrawal of consent to PD Processing and provides a response to it in accordance with the legislation of the Russian Federation. The form for the appeal of the Personal Data Subject/withdrawal of consent to PD Processing is posted on the Internet at https://dexarmarket.ru.</p>
|
||||
<p>6.17. Օպերատորը քննում է Անձնական տվյալների սուբյեկտի դիմումը/ԱՏ մշակման համաձայնության հետկանչը և պատասխանում է դրան` Ռուսաստանի Դաշնության օրենսդրությանը համապատասխան։ Անձնական տվյալների սուբյեկտի դիմումի/ԱՏ մշակման համաձայնության հետկանչի ձևը տեղադրված է ինտերնետում` https://dexarmarket.ru հասցեում։</p>
|
||||
|
||||
<h3>6.18. Confidentiality of Personal Data</h3>
|
||||
<p>Personal data is not disclosed to third parties and is not distributed otherwise without the consent of the Personal Data Subject, unless otherwise provided by the legislation of the Russian Federation. When disclosing (providing) Personal Data to third parties, the requirements for the protection of Processed Personal Data are observed.</p>
|
||||
<h3>6.18. Անձնական տվյալների գաղտնիությունը</h3>
|
||||
<p>Անձնական տվյալները չեն բացահայտվում երրորդ անձանց և այլ կերպ չեն տարածվում առանց Անձնական տվյալների սուբյեկտի համաձայնության, եթե այլ բան նախատեսված չէ Ռուսաստանի Դաշնության օրենսդրությամբ։ Երրորդ անձանց անձնական տվյալներ բացահայտելիս (տրամադրելիս) պահպանվում են մշակվող անձնական տվյալների պաշտպանության պահանջները։</p>
|
||||
|
||||
<h3>6.19. Publicly Available Sources of Personal Data</h3>
|
||||
<p>For information purposes, the Operator may create publicly available sources of PD of PD Subjects, including directories and address books. With the written consent of the PD Subject, their surname, first name, place of birth, contact phone number, email address, and other Personal Data communicated by the PD Subject may be included in publicly available PD sources.</p>
|
||||
<h3>6.19. Անձնական տվյալների հանրամատչելի աղբյուրներ</h3>
|
||||
<p>Տեղեկատվական նպատակներով Օպերատորը կարող է ստեղծել ԱՏ սուբյեկտների ԱՏ հանրամատչելի աղբյուրներ, ներառյալ տեղեկագրքեր և հասցեական գրքեր։ ԱՏ սուբյեկտի գրավոր համաձայնությամբ հանրամատչելի աղբյուրներում կարող են ներառվել նրա ազգանունը, անունը, ծննդավայրը, կոնտակտային հեռախոսահամարը, էլեկտրոնային փոստի հասցեն և ԱՏ սուբյեկտի կողմից հաղորդված այլ անձնական տվյալներ։</p>
|
||||
|
||||
<p>Information about the PD Subject must be excluded from publicly available PD sources at any time at the request of the PD Subject, the authorized body for the protection of PD Subjects' rights, or by court order.</p>
|
||||
<p>ԱՏ սուբյեկտի վերաբերյալ տեղեկությունները պետք է ցանկացած ժամանակ բացառվեն հանրամատչելի աղբյուրներից` ԱՏ սուբյեկտի, ԱՏ սուբյեկտների իրավունքների պաշտպանության լիազորված մարմնի պահանջով կամ դատարանի որոշմամբ։</p>
|
||||
|
||||
<h3>6.20. Special Categories of Personal Data</h3>
|
||||
<p>Processing of special categories of PD by the Operator is permitted in the cases specified in Article 10 of FZ-152. Processing of PD about criminal records may be carried out by the Operator exclusively in cases and in the manner determined in accordance with the legislation of the Russian Federation.</p>
|
||||
<h3>6.20. Անձնական տվյալների հատուկ կատեգորիաներ</h3>
|
||||
<p>Օպերատորի կողմից ԱՏ հատուկ կատեգորիաների մշակումը թույլատրվում է թիվ 152-ՖԶ օրենքի 10-րդ հոդվածում նշված դեպքերում։ Դատվածության վերաբերյալ ԱՏ մշակումը կարող է Օպերատորի կողմից իրականացվել բացառապես այն դեպքերում և կարգով, որոնք սահմանվում են Ռուսաստանի Դաշնության օրենսդրությանը համապատասխան։</p>
|
||||
|
||||
<h3>6.21. Biometric Personal Data</h3>
|
||||
<p>Information that characterizes the physiological and biological features of a person, on the basis of which their identity can be established — biometric Personal Data — may be processed by the Operator only with the written consent of the PD Subject.</p>
|
||||
<h3>6.21. Կենսաչափական անձնական տվյալներ</h3>
|
||||
<p>Տեղեկատվությունը, որը բնութագրում է անձի ֆիզիոլոգիական և կենսաբանական առանձնահատկությունները և որի հիման վրա հնարավոր է հաստատել նրա ինքնությունը` կենսաչափական անձնական տվյալները, կարող է Օպերատորի կողմից մշակվել միայն ԱՏ սուբյեկտի գրավոր համաձայնությամբ։</p>
|
||||
|
||||
<h3>6.22. Entrusting Personal Data Processing to Another Person</h3>
|
||||
<p>The Operator has the right to entrust PD Processing to another person with the consent of the PD Subject, unless otherwise provided by federal law, on the basis of a contract concluded with that person. The person carrying out PD Processing on behalf of the Operator is obliged to comply with the principles and rules of PD Processing provided for by FZ-152 and this Policy.</p>
|
||||
<h3>6.22. Անձնական տվյալների մշակումը այլ անձի հանձնարարված լինելը</h3>
|
||||
<p>Օպերատորն իրավունք ունի ԱՏ սուբյեկտի համաձայնությամբ ԱՏ մշակումը հանձնել այլ անձի, եթե այլ բան նախատեսված չէ դաշնային օրենքով, այդ անձի հետ կնքված պայմանագրի հիման վրա։ Օպերատորի հանձնարարությամբ ԱՏ մշակող անձը պարտավոր է պահպանել թիվ 152-ՖԶ օրենքով և սույն Քաղաքականությամբ նախատեսված ԱՏ մշակման սկզբունքներն ու կանոնները։</p>
|
||||
|
||||
<h3>6.23. Processing of Personal Data of Citizens of the Russian Federation</h3>
|
||||
<p>In accordance with Article 2 of Federal Law No. 242-FZ of July 21, 2014, when collecting PD, including through the information and telecommunications network "Internet", the Operator is obliged to ensure the recording, systematization, accumulation, storage, clarification (updating, modification), extraction of PD of citizens of the Russian Federation using databases located on the territory of the Russian Federation, except in cases established by legislation.</p>
|
||||
<h3>6.23. Ռուսաստանի Դաշնության քաղաքացիների անձնական տվյալների մշակում</h3>
|
||||
<p>2014 թվականի հուլիսի 21-ի թիվ 242-ՖԶ դաշնային օրենքի 2-րդ հոդվածի համաձայն` ԱՏ հավաքագրելիս, այդ թվում` «Ինտերնետ» տեղեկատվա-հեռահաղորդակցական ցանցի միջոցով, Օպերատորը պարտավոր է ապահովել Ռուսաստանի Դաշնության քաղաքացիների ԱՏ գրանցումը, համակարգումը, կուտակումը, պահպանումը, ճշգրտումը (թարմացումը, փոփոխումը), քաղումը` օգտագործելով տվյալների բազաներ, որոնք գտնվում են Ռուսաստանի Դաշնության տարածքում, բացառությամբ օրենսդրությամբ սահմանված դեպքերի։</p>
|
||||
|
||||
<h3>6.24. Cross-border Transfer of Personal Data</h3>
|
||||
<p>The Operator is obliged to ensure that the foreign state to whose territory PD is intended to be transferred provides adequate protection of the rights of PD Subjects before carrying out such transfer.</p>
|
||||
<h3>6.24. Անձնական տվյալների անդրսահմանային փոխանցում</h3>
|
||||
<p>Օպերատորը պարտավոր է մինչև նման փոխանցումն իրականացնելը համոզվել, որ այն օտարերկրյա պետությունը, որի տարածք նախատեսվում է փոխանցել ԱՏ, ապահովում է ԱՏ սուբյեկտների իրավունքների բավարար պաշտպանություն։</p>
|
||||
|
||||
<p>Cross-border transfer of PD to the territories of foreign states that do not provide adequate protection of the rights of PD Subjects may be carried out in the following cases:</p>
|
||||
<p>ԱՏ անդրսահմանային փոխանցումը այն օտարերկրյա պետությունների տարածք, որոնք չեն ապահովում ԱՏ սուբյեկտների իրավունքների բավարար պաշտպանություն, կարող է իրականացվել հետևյալ դեպքերում.</p>
|
||||
<ul>
|
||||
<li>the written consent of the PD Subject to the cross-border transfer of their PD;</li>
|
||||
<li>performance of a contract to which the PD Subject is a party.</li>
|
||||
<li>ԱՏ սուբյեկտի գրավոր համաձայնությունը իր ԱՏ անդրսահմանային փոխանցման վերաբերյալ,</li>
|
||||
<li>պայմանագրի կատարում, որի կողմ է ԱՏ սուբյեկտը։</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section class="legal-section">
|
||||
<h2>7. RIGHTS OF THE PERSONAL DATA SUBJECT</h2>
|
||||
<h2>7. ԱՆՁՆԱԿԱՆ ՏՎՅԱԼՆԵՐԻ ՍՈՒԲՅԵԿՏԻ ԻՐԱՎՈՒՆՔՆԵՐԸ</h2>
|
||||
|
||||
<h3>7.1. Consent of the Personal Data Subject</h3>
|
||||
<p>The PD Subject makes the decision to provide their PD and gives consent to their Processing freely, of their own will and in their own interest. Consent to PD Processing may be given by the PD Subject or their representative in any form that allows confirmation of the fact of receiving it, unless otherwise established by FZ-152.</p>
|
||||
<h3>7.1. Անձնական տվյալների սուբյեկտի համաձայնությունը</h3>
|
||||
<p>ԱՏ սուբյեկտը որոշում է տրամադրել իր ԱՏ-ն և տալիս է համաձայնություն դրանց մշակման համար ազատորեն, սեփական կամքով և իր շահերից ելնելով։ ԱՏ մշակման համաձայնությունը կարող է տրվել ԱՏ սուբյեկտի կամ նրա ներկայացուցչի կողմից ցանկացած ձևով, որը թույլ է տալիս հաստատել այն ստանալու փաստը, եթե այլ բան սահմանված չէ թիվ 152-ՖԶ օրենքով։</p>
|
||||
|
||||
<p>Processing of PD for the purpose of promoting goods, works, services on the market by making direct contacts with the PD Subject (potential consumer) using communication means, as well as for political campaigning, is permitted only upon prior consent of the PD Subject.</p>
|
||||
<p>ԱՏ մշակումը ապրանքների, աշխատանքների, ծառայությունների շուկայում առաջխաղացման նպատակով` ԱՏ սուբյեկտի (պոտենցիալ սպառողի) հետ կապի միջոցների միջոցով անմիջական կապ հաստատելով, ինչպես նաև քաղաքական քարոզչության համար թույլատրվում է միայն ԱՏ սուբյեկտի նախնական համաձայնությամբ։</p>
|
||||
|
||||
<h3>7.2. Rights of the Personal Data Subject</h3>
|
||||
<p>The PD Subject has the right to obtain from the Operator information regarding the Processing of their PD, if such a right is not restricted in accordance with the legislation of the Russian Federation, including information containing:</p>
|
||||
<h3>7.2. Անձնական տվյալների սուբյեկտի իրավունքները</h3>
|
||||
<p>ԱՏ սուբյեկտն իրավունք ունի Օպերատորից ստանալու տեղեկատվություն իր ԱՏ մշակման վերաբերյալ, եթե նման իրավունքը սահմանափակված չէ Ռուսաստանի Դաշնության օրենսդրությանը համապատասխան, ներառյալ տեղեկատվություն, որը պարունակում է.</p>
|
||||
<ul>
|
||||
<li>confirmation of the fact of PD Processing by the Operator;</li>
|
||||
<li>legal grounds and purposes of PD Processing;</li>
|
||||
<li>methods of PD Processing used by the Operator;</li>
|
||||
<li>information about the name and location of the Operator;</li>
|
||||
<li>list and categories of Processed PD;</li>
|
||||
<li>periods of Personal Data Processing, including storage periods;</li>
|
||||
<li>the name or surname, first name, patronymic, and address of the person carrying out PD Processing on behalf of the Operator;</li>
|
||||
<li>clarification of their PD, their Blocking or Destruction if the PD is incomplete, outdated, or inaccurate;</li>
|
||||
<li>other information provided for by FZ-152 or other federal laws of the Russian Federation.</li>
|
||||
<li>Օպերատորի կողմից ԱՏ մշակման փաստի հաստատում,</li>
|
||||
<li>ԱՏ մշակման իրավական հիմքերն ու նպատակները,</li>
|
||||
<li>Օպերատորի կողմից օգտագործվող ԱՏ մշակման եղանակները,</li>
|
||||
<li>Օպերատորի անվանման և գտնվելու վայրի մասին տեղեկատվություն,</li>
|
||||
<li>մշակվող ԱՏ ցանկը և կատեգորիաները,</li>
|
||||
<li>անձնային տվյալների մշակման ժամկետները, ներառյալ պահման ժամկետները,</li>
|
||||
<li>Օպերատորի հանձնարարությամբ ԱՏ մշակող անձի անունը կամ ազգանունը, անունը, հայրանունը և հասցեն,</li>
|
||||
<li>իր ԱՏ ճշգրտումը, դրանց արգելափակումը կամ ոչնչացումը, եթե ԱՏ-ն թերի են, հնացած կամ ոչ ճշգրիտ,</li>
|
||||
<li>այլ տեղեկատվություն, որը նախատեսված է թիվ 152-ՖԶ օրենքով կամ Ռուսաստանի Դաշնության այլ դաշնային օրենքներով։</li>
|
||||
</ul>
|
||||
|
||||
<p>The Operator is obliged to immediately cease Processing of PD at the request of the PD Subject.</p>
|
||||
<p>Օպերատորը պարտավոր է ԱՏ սուբյեկտի պահանջով անհապաղ դադարեցնել ԱՏ մշակումը։</p>
|
||||
|
||||
<p>If the PD Subject believes that the Operator is Processing their PD in violation of the requirements of FZ-152 or otherwise violates their rights and freedoms, the PD Subject has the right to appeal the actions or inaction of the Operator to the authorized body for the protection of PD Subjects' rights or in court.</p>
|
||||
<p>Եթե ԱՏ սուբյեկտը կարծում է, որ Օպերատորը մշակում է իր ԱՏ-ն` խախտելով թիվ 152-ՖԶ օրենքի պահանջները կամ այլ կերպ խախտում է իր իրավունքներն ու ազատությունները, ԱՏ սուբյեկտն իրավունք ունի բողոքարկել Օպերատորի գործողությունները կամ անգործությունը ԱՏ սուբյեկտների իրավունքների պաշտպանության լիազորված մարմնում կամ դատարանում։</p>
|
||||
|
||||
<p>The PD Subject has the right to protect their rights and legitimate interests, including compensation for losses and/or moral damages.</p>
|
||||
<p>ԱՏ սուբյեկտն իրավունք ունի պաշտպանելու իր իրավունքներն ու օրինական շահերը, ներառյալ վնասների և/կամ բարոյական վնասի փոխհատուցման պահանջով։</p>
|
||||
|
||||
<p>The PD Subject has the right to demand correction of their Personal Data if inaccuracies are found in the PD processed by the Operator, as well as to supplement the PD, including by providing an additional statement.</p>
|
||||
<p>ԱՏ սուբյեկտն իրավունք ունի պահանջել իր Անձնական տվյալների ուղղում, եթե Օպերատորի կողմից մշակվող ԱՏ-ում հայտնաբերվեն անճշտություններ, ինչպես նաև լրացնել ԱՏ-ն, այդ թվում` լրացուցիչ հայտարարություն ներկայացնելու միջոցով։</p>
|
||||
|
||||
<p><strong>The PD Subject has the right to withdraw their Consent to Personal Data Processing and to demand the deletion of their PD</strong> from the Operator's systems if the PD is no longer required for the purposes for which it was obtained. You can withdraw your consent to Personal Data Processing at any time by sending an electronic message with an electronic signature to the email address: <a href="mailto:info@dexarmarket.ru">info@dexarmarket.ru</a>, or by sending a written notice to the Operator's registered address.</p>
|
||||
<p><strong>ԱՏ սուբյեկտն իրավունք ունի հետ կանչել իր համաձայնությունը Անձնական տվյալների մշակման վերաբերյալ և պահանջել իր ԱՏ ջնջումը</strong> Օպերատորի համակարգերից, եթե այդ ԱՏ-ն այլևս անհրաժեշտ չեն այն նպատակների համար, որոնց համար ստացվել են։ Դուք կարող եք ցանկացած ժամանակ հետ կանչել ձեր համաձայնությունը Անձնական տվյալների մշակման վերաբերյալ` ուղարկելով էլեկտրոնային հաղորդագրություն էլեկտրոնային ստորագրությամբ հետևյալ հասցեին` <a href="mailto:info@dexarmarket.ru">info@dexarmarket.ru</a>, կամ ուղարկելով գրավոր ծանուցում Օպերատորի գրանցված հասցեին։</p>
|
||||
|
||||
<p>The Personal Data Subject has the right to demand the restriction of Processing of their Personal Data for the purposes of the Operator's advertising offers.</p>
|
||||
<p>Անձնական տվյալների սուբյեկտն իրավունք ունի պահանջել սահմանափակել իր Անձնական տվյալների մշակումը Օպերատորի գովազդային առաջարկների նպատակներով։</p>
|
||||
|
||||
<p>The Personal Data Subject also has other rights established by FZ-152.</p>
|
||||
<p>Անձնական տվյալների սուբյեկտն ունի նաև այլ իրավունքներ, որոնք սահմանված են թիվ 152-ՖԶ օրենքով։</p>
|
||||
|
||||
<p>The Personal Data Subject whose PD is Processed by the Operator has the right at any time to change (update, supplement) the PD they have provided by logging into their personal account in cases where the functionality of the relevant Website allows this.</p>
|
||||
<p>Անձնական տվյալների սուբյեկտը, որի ԱՏ-ն մշակվում են Օպերատորի կողմից, իրավունք ունի ցանկացած պահի փոխել (թարմացնել, լրացնել) իր կողմից տրամադրված ԱՏ-ն` մուտք գործելով իր անձնական հաշիվ այն դեպքերում, երբ համապատասխան Կայքի ֆունկցիոնալությունը դա թույլ է տալիս։</p>
|
||||
</section>
|
||||
|
||||
<section class="legal-section">
|
||||
<h2>8. OBLIGATIONS OF THE OPERATOR</h2>
|
||||
<h2>8. ՕՊԵՐԱՏՈՐԻ ՊԱՐՏԱԿԱՆՈՒԹՅՈՒՆՆԵՐԸ</h2>
|
||||
|
||||
<p>8.1. In cases established by the legislation of the Russian Federation in the field of Personal Data, the Operator is obliged to provide the Personal Data Subject or their representative, upon request or upon receipt of a request from the Personal Data Subject or their representative, with the information provided for in clause 7.2 of this Policy.</p>
|
||||
<p>8.1. Ռուսաստանի Դաշնության անձնական տվյալների ոլորտի օրենսդրությամբ սահմանված դեպքերում Օպերատորը պարտավոր է Անձնական տվյալների սուբյեկտին կամ նրա ներկայացուցչին, պահանջի դեպքում կամ նրանցից հարցում ստանալու դեպքում, տրամադրել սույն Քաղաքականության 7.2 կետով նախատեսված տեղեկատվությունը։</p>
|
||||
|
||||
<p>8.2. When collecting Personal Data, including through the information and telecommunications network "Internet", the Operator ensures the recording, systematization, accumulation, storage, clarification (updating, modification), extraction of Personal Data of citizens of the Russian Federation using databases located in the territory of the Russian Federation, except in cases provided for by Federal Law No. 152-FZ.</p>
|
||||
<p>8.2. Անձնական տվյալներ հավաքագրելիս, այդ թվում` «Ինտերնետ» տեղեկատվա-հեռահաղորդակցական ցանցի միջոցով, Օպերատորը ապահովում է Ռուսաստանի Դաշնության քաղաքացիների անձնական տվյալների գրանցումը, համակարգումը, կուտակումը, պահպանումը, ճշգրտումը (թարմացումը, փոփոխումը), քաղումը` օգտագործելով Ռուսաստանի Դաշնության տարածքում գտնվող տվյալների բազաներ, բացառությամբ թիվ 152-ՖԶ դաշնային օրենքով նախատեսված դեպքերի։</p>
|
||||
|
||||
<p>8.3. The Operator bears other obligations established by Federal Law No. 152-FZ.</p>
|
||||
<p>8.3. Օպերատորը կրում է նաև այլ պարտականություններ, որոնք սահմանված են թիվ 152-ՖԶ դաշնային օրենքով։</p>
|
||||
</section>
|
||||
|
||||
<section class="legal-section">
|
||||
<h2>9. ENSURING PERSONAL DATA SECURITY</h2>
|
||||
<h2>9. ԱՆՁՆԱԿԱՆ ՏՎՅԱԼՆԵՐԻ ԱՆՎՏԱՆԳՈՒԹՅԱՆ ԱՊԱՀՈՎՈՒՄ</h2>
|
||||
|
||||
<p>9.1. The Operator independently determines the composition and list of measures necessary and sufficient to ensure the fulfillment of obligations provided for by Federal Law No. 152-FZ and regulatory legal acts adopted in accordance with it.</p>
|
||||
<p>9.1. Օպերատորն ինքնուրույն որոշում է այն միջոցների կազմն ու ցանկը, որոնք անհրաժեշտ և բավարար են թիվ 152-ՖԶ դաշնային օրենքով և դրա հիման վրա ընդունված նորմատիվ իրավական ակտերով նախատեսված պարտավորությունների կատարման ապահովման համար։</p>
|
||||
|
||||
<p>9.2. The security of PD Processed by the Operator is ensured by the implementation of legal, organizational, and technical measures necessary to meet the requirements of federal legislation in the field of PD protection.</p>
|
||||
<p>9.2. Օպերատորի կողմից մշակվող ԱՏ անվտանգությունն ապահովվում է իրավական, կազմակերպական և տեխնիկական միջոցառումների իրականացման միջոցով, որոնք անհրաժեշտ են դաշնային օրենսդրության պահանջներին համապատասխանելու համար ԱՏ պաշտպանության ոլորտում։</p>
|
||||
|
||||
<p>9.3. To prevent unauthorized access to PD, the Operator applies the following organizational and technical measures:</p>
|
||||
<p>9.3. ԱՏ նկատմամբ չարտոնված հասանելիությունը կանխելու նպատակով Օպերատորը կիրառում է հետևյալ կազմակերպական և տեխնիկական միջոցները.</p>
|
||||
<ul>
|
||||
<li>appointment of officials responsible for organizing PD Processing and protection;</li>
|
||||
<li>limitation of the number of persons authorized to Process PD;</li>
|
||||
<li>familiarization of PD Subjects with the requirements of federal legislation and the Operator's regulatory documents on PD Processing and protection;</li>
|
||||
<li>organization of accounting, storage, and handling of carriers containing information with Personal Data;</li>
|
||||
<li>development and approval of local acts on PD Processing and protection;</li>
|
||||
<li>identification of PD security threats during their Processing, forming threat models based on them;</li>
|
||||
<li>development of a PD protection system based on the threat model;</li>
|
||||
<li>verification of the readiness and effectiveness of information protection tools;</li>
|
||||
<li>differentiation of User access to information resources and hardware and software tools for information Processing;</li>
|
||||
<li>registration and recording of User actions in information systems;</li>
|
||||
<li>use of antivirus tools;</li>
|
||||
<li>conducting activities to detect facts of unauthorized access to PD and taking appropriate measures;</li>
|
||||
<li>compliance with conditions that exclude unauthorized access to material carriers of Personal Data;</li>
|
||||
<li>application, when necessary, of firewalling, intrusion detection, security analysis, and cryptographic information protection tools;</li>
|
||||
<li>organization of access control to the Operator's territory, protection of premises with technical means of Personal Data Processing;</li>
|
||||
<li>monitoring of measures taken to ensure PD security.</li>
|
||||
<li>ԱՏ մշակման և պաշտպանության կազմակերպման համար պատասխանատու պաշտոնատար անձանց նշանակում,</li>
|
||||
<li>ԱՏ մշակելու իրավասություն ունեցող անձանց թվի սահմանափակում,</li>
|
||||
<li>ԱՏ սուբյեկտներին ծանոթացում դաշնային օրենսդրության և Օպերատորի նորմատիվ փաստաթղթերի պահանջներին` ԱՏ մշակման և պաշտպանության մասով,</li>
|
||||
<li>Անձնական տվյալներ պարունակող կրիչների հաշվառման, պահպանման և շրջանառության կազմակերպում,</li>
|
||||
<li>ԱՏ մշակման և պաշտպանության վերաբերյալ տեղական ակտերի մշակում և հաստատում,</li>
|
||||
<li>ԱՏ մշակման ընթացքում դրանց անվտանգության սպառնալիքների բացահայտում և դրանց հիման վրա սպառնալիքների մոդելների ձևավորում,</li>
|
||||
<li>սպառնալիքների մոդելի հիման վրա ԱՏ պաշտպանության համակարգի մշակում,</li>
|
||||
<li>տեղեկատվության պաշտպանության միջոցների պատրաստվածության և արդյունավետության ստուգում,</li>
|
||||
<li>Օգտատերերի հասանելիության տարբերակում տեղեկատվական ռեսուրսների և տեղեկատվության մշակման ապարատա-ծրագրային միջոցների նկատմամբ,</li>
|
||||
<li>Օգտատերերի գործողությունների գրանցում և հաշվառում տեղեկատվական համակարգերում,</li>
|
||||
<li>հակավիրուսային միջոցների օգտագործում,</li>
|
||||
<li>ԱՏ նկատմամբ չարտոնված հասանելիության փաստերի հայտնաբերման և համապատասխան միջոցների կիրառման միջոցառումների անցկացում,</li>
|
||||
<li>այնպիսի պայմանների պահպանում, որոնք բացառում են անձնական տվյալների նյութական կրիչների նկատմամբ չարտոնված հասանելիությունը,</li>
|
||||
<li>անհրաժեշտության դեպքում firewall-ների, ներխուժումների հայտնաբերման, անվտանգության վերլուծության և տեղեկատվության ծածկագրային պաշտպանության միջոցների կիրառում,</li>
|
||||
<li>Օպերատորի տարածք մուտքի վերահսկման կազմակերպում, ինչպես նաև անձնական տվյալների մշակման տեխնիկական միջոցներով հագեցած տարածքների պաշտպանություն,</li>
|
||||
<li>ԱՏ անվտանգության ապահովմանն ուղղված ձեռնարկված միջոցների վերահսկում։</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section class="legal-section">
|
||||
<h2>10. LIABILITY</h2>
|
||||
<h2>10. ՊԱՏԱՍԽԱՆԱՏՎՈՒԹՅՈՒՆ</h2>
|
||||
|
||||
<p>10.1. Persons guilty of violating the norms regulating the Processing of Personal Data and the protection of Personal Data Processed by the Operator bear liability as provided by the legislation of the Russian Federation.</p>
|
||||
<p>10.1. Այն անձինք, որոնք մեղավոր են անձնական տվյալների մշակումը և Օպերատորի կողմից մշակվող անձնական տվյալների պաշտպանությունը կարգավորող նորմերի խախտման մեջ, կրում են պատասխանատվություն` Ռուսաստանի Դաշնության օրենսդրությամբ սահմանված կարգով։</p>
|
||||
</section>
|
||||
|
||||
<section class="legal-section">
|
||||
<h2>11. PURPOSES OF PERSONAL INFORMATION PROCESSING</h2>
|
||||
<h2>11. ԱՆՁՆԱԿԱՆ ՏԵՂԵԿԱՏՎՈՒԹՅԱՆ ՄՇԱԿՄԱՆ ՆՊԱՏԱԿՆԵՐԸ</h2>
|
||||
|
||||
<p>11.1. The Operator always Processes PD for specific purposes and only the PD that is relevant to the achievement of such purposes. In particular, the Operator processes PD for the following purposes:</p>
|
||||
<p>11.1. Օպերատորը միշտ մշակում է ԱՏ կոնկրետ նպատակներով և միայն այն ԱՏ-ն, որոնք առնչվում են այդ նպատակներին հասնելուն։ Մասնավորապես, Օպերատորը մշակում է ԱՏ հետևյալ նպատակներով.</p>
|
||||
<ul>
|
||||
<li>Providing the User with access to the relevant Website;</li>
|
||||
<li>Providing access to the User's account (personal cabinet) on the relevant Website;</li>
|
||||
<li>For the execution of a purchase and sale agreement, a service agreement, or other agreement between the Seller and the User;</li>
|
||||
<li>Delivery of goods of the Seller and/or the Operator to Users;</li>
|
||||
<li>Assistance in settling claims between the User and the Seller;</li>
|
||||
<li>Settlement of claims between the User and the Operator;</li>
|
||||
<li>Execution of instructions of the Seller and/or the Operator regarding the collection and transfer of funds received for goods and/or services;</li>
|
||||
<li>Improving the quality of User service, market study and analysis, studying User needs;</li>
|
||||
<li>Receiving feedback regarding goods and/or services posted on the Websites;</li>
|
||||
<li>Execution of instructions of Sellers and Users in connection with the refusal to accept services and/or return of goods;</li>
|
||||
<li>Posting User reviews of goods and/or services;</li>
|
||||
<li>Analysis of the quality of the service provided by the Operator and improvement of customer service quality;</li>
|
||||
<li>For the implementation of labor agreements in accordance with the legislation of the Russian Federation;</li>
|
||||
<li>Making a decision on hiring a candidate;</li>
|
||||
<li>Fulfillment of obligations arising from the conclusion of contractual relations between the Operator and third parties;</li>
|
||||
<li>Providing responses to requests from individuals;</li>
|
||||
<li>Conducting marketing and other research;</li>
|
||||
<li>Sending advertising and informational messages about goods and/or services of Sellers, as well as goods and/or services of the Operator and advertising personalization;</li>
|
||||
<li>In any other cases directly provided for by the current legislation of the Russian Federation.</li>
|
||||
<li>Օգտատիրոջը համապատասխան Կայքին հասանելիություն տրամադրելու համար,</li>
|
||||
<li>համապատասխան Կայքում Օգտատիրոջ հաշվին (անձնական կաբինետին) հասանելիություն տրամադրելու համար,</li>
|
||||
<li>Վաճառողի և Օգտատիրոջ միջև առուվաճառքի պայմանագրի, ծառայությունների մատուցման պայմանագրի կամ այլ պայմանագրի կատարման համար,</li>
|
||||
<li>Վաճառողի և/կամ Օպերատորի ապրանքների առաքման համար Օգտատերերին,</li>
|
||||
<li>Օգտատիրոջ և Վաճառողի միջև պահանջների կարգավորման հարցում աջակցելու համար,</li>
|
||||
<li>Օգտատիրոջ և Օպերատորի միջև պահանջների կարգավորման համար,</li>
|
||||
<li>Վաճառողի և/կամ Օպերատորի հանձնարարությունների կատարման համար` ապրանքների և/կամ ծառայությունների դիմաց ստացված միջոցների հավաքագրման և փոխանցման մասով,</li>
|
||||
<li>Օգտատերերի սպասարկման որակը բարելավելու, շուկայի ուսումնասիրման և վերլուծության, Օգտատերերի պահանջների ուսումնասիրման համար,</li>
|
||||
<li>Կայքերում տեղադրված ապրանքների և/կամ ծառայությունների վերաբերյալ հետադարձ կապ ստանալու համար,</li>
|
||||
<li>Վաճառողների և Օգտատերերի հանձնարարությունների կատարման համար` կապված ծառայություններից հրաժարվելու և/կամ ապրանքների վերադարձի հետ,</li>
|
||||
<li>Օգտատերերի կարծիքները ապրանքների և/կամ ծառայությունների վերաբերյալ հրապարակելու համար,</li>
|
||||
<li>Օպերատորի կողմից մատուցվող ծառայությունների որակը վերլուծելու և հաճախորդների սպասարկման որակը բարելավելու համար,</li>
|
||||
<li>Ռուսաստանի Դաշնության օրենսդրությանը համապատասխան աշխատանքային պայմանագրերի իրականացման համար,</li>
|
||||
<li>թեկնածուի աշխատանքի ընդունման վերաբերյալ որոշում կայացնելու համար,</li>
|
||||
<li>Օպերատորի և երրորդ անձանց միջև պայմանագրային հարաբերությունների կնքումից բխող պարտավորությունների կատարման համար,</li>
|
||||
<li>ֆիզիկական անձանց հարցումներին պատասխաններ տրամադրելու համար,</li>
|
||||
<li>մարքեթինգային և այլ հետազոտություններ իրականացնելու համար,</li>
|
||||
<li>Վաճառողների ապրանքների և/կամ ծառայությունների, ինչպես նաև Օպերատորի ապրանքների և/կամ ծառայությունների վերաբերյալ գովազդային և տեղեկատվական հաղորդագրություններ ուղարկելու և գովազդի անհատականացման համար,</li>
|
||||
<li>Ռուսաստանի Դաշնության գործող օրենսդրությամբ ուղղակիորեն նախատեսված այլ դեպքերում։</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section class="legal-section">
|
||||
<h2>12. AUTOMATICALLY COLLECTED INFORMATION</h2>
|
||||
<h2>12. ԻՆՔՆԱԲԵՐԱԲԱՐ ՀԱՎԱՔՎՈՂ ՏԵՂԵԿԱՏՎՈՒԹՅՈՒՆ</h2>
|
||||
|
||||
<p>12.1. The Operator has the right to collect and Process, including information that is not PD:</p>
|
||||
<p>12.1. Օպերատորն իրավունք ունի հավաքագրել և մշակել, այդ թվում` տեղեկատվություն, որը չի հանդիսանում ԱՏ.</p>
|
||||
<ul>
|
||||
<li>information about User interests on the Websites based on search queries entered by Website Users in order to provide relevant information to Users when using the Websites;</li>
|
||||
<li>information that forms the system rating of the Seller/Operator: User reviews of the Seller/Operator, information on Order fulfillment, other information;</li>
|
||||
<li>The Operator processes and stores search queries of Website Users for the purpose of generalizing and creating customer statistics on the use of Website sections.</li>
|
||||
<li>տեղեկատվություն Օգտատերերի հետաքրքրությունների մասին Կայքերում` հիմնված Կայքերի Օգտատերերի կողմից մուտքագրված որոնողական հարցումների վրա, որպեսզի Կայքերից օգտվելիս Օգտատերերին տրամադրվի համապատասխան տեղեկատվություն,</li>
|
||||
<li>տեղեկատվություն, որը ձևավորում է Վաճառողի/Օպերատորի համակարգային վարկանիշը` Օգտատերերի կարծիքները Վաճառողի/Օպերատորի մասին, Պատվերների կատարման վերաբերյալ տեղեկատվությունը, այլ տեղեկատվություն,</li>
|
||||
<li>Օպերատորը մշակում և պահպանում է Կայքերի Օգտատերերի որոնողական հարցումները` Կայքի բաժինների օգտագործման վերաբերյալ հաճախորդների վիճակագրությունը ընդհանրացնելու և ստեղծելու նպատակով։</li>
|
||||
</ul>
|
||||
|
||||
<p>12.2. The Operator automatically receives certain types of information obtained in the process of User interaction with the Websites. This refers to technologies and services such as web protocols, cookies, web beacons, as well as third-party applications and tools. At the same time, web beacons, cookies, and other monitoring technologies do not allow the automatic collection of PD.</p>
|
||||
<p>12.2. Օպերատորն ավտոմատ կերպով ստանում է որոշակի տեսակի տեղեկատվություն, որը ձևավորվում է Օգտատերերի կողմից Կայքերի հետ փոխգործակցության ընթացքում։ Խոսքը վերաբերում է այնպիսի տեխնոլոգիաների և ծառայությունների, ինչպիսիք են web protocol-ները, cookie-ները, web beacon-ները, ինչպես նաև երրորդ կողմի հավելվածներն ու գործիքները։ Միևնույն ժամանակ, web beacon-ները, cookie-ները և վերահսկման այլ տեխնոլոգիաները չեն թույլատրում ավտոմատ կերպով հավաքագրել ԱՏ։</p>
|
||||
|
||||
<p>12.3. If the Operator can reasonably associate the information specified in this section with the personal account of a specific User, then such information may be processed together with the PD and other personal information of such User.</p>
|
||||
<p>12.3. Եթե Օպերատորը կարող է ողջամտորեն կապել սույն բաժնում նշված տեղեկատվությունը կոնկրետ Օգտատիրոջ անձնական հաշվի հետ, ապա այդպիսի տեղեկատվությունը կարող է մշակվել տվյալ Օգտատիրոջ ԱՏ և այլ անձնական տեղեկատվության հետ միասին։</p>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
@@ -5,7 +5,7 @@
|
||||
<section class="legal-section">
|
||||
<h2>1. ОБЩИЕ ПОЛОЖЕНИЯ</h2>
|
||||
|
||||
<p>1.1. Настоящая политика ООО "ИНТ ФИН ЛОГИСТИК" (ИНН 9909697628), именуемого далее как «Оператор», описывает порядок обработки персональных данных и направлена на защиту прав и законных интересов субъектов данных. Документ разработан в соответствии с Федеральным законом №152-ФЗ от 27 июля 2006 года «О персональных данных».</p>
|
||||
<p>1.1. Настоящая политика ООО "ИНТ ФИН ЛОГИСТИК" (ИНН 9909697628) и ООО "ИНТ ФАКТОРИНГ" (ИНН 9909697635), именуемых далее как «Оператор», описывает порядок обработки персональных данных и направлена на защиту прав и законных интересов субъектов данных. Документ разработан в соответствии с Федеральным законом №152-ФЗ от 27 июля 2006 года «О персональных данных».</p>
|
||||
|
||||
<p>1.2. Политика определяет порядок и меры обеспечения безопасности обработки персональных данных на сайте <a href="https://dexarmarket.ru">https://dexarmarket.ru</a>, ставя своей задачей защитить права и свободы человека и гражданина, включая право на неприкосновенность частной жизни, личную и семейную тайны.</p>
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
|
||||
<li><strong>Buyer</strong> — a registered User who has placed an order through the site.</li>
|
||||
|
||||
<li><strong>Administrator or Site Owner</strong> — the legal entity INT FIN LOGISTIK LLC, tax identification number (TIN) 9909697628.</li>
|
||||
<li><strong>Administrator or Site Owner</strong> — the legal entities INT FIN LOGISTIK LLC (TIN 9909697628) and INT FACTORING LLC (TIN 9909697635).</li>
|
||||
|
||||
<li><strong>Seller</strong> — individuals or legal entities, entrepreneurs offering goods and services on the resource. Sellers bear personal responsibility for the quality, safety and compliance of the product descriptions.</li>
|
||||
|
||||
@@ -177,6 +177,62 @@
|
||||
|
||||
<p><strong>6.3. User Rights</strong></p>
|
||||
<p>The User has the right to refuse to receive advertising messages by using the appropriate tool on the site or by sending a request by email to <a href="mailto:info@dexarmarket.ru">info@dexarmarket.ru</a> or by letter to the official address of the Site Owner.</p>
|
||||
|
||||
<p><strong>6.4. Prohibited Goods for Sale on the Site</strong></p>
|
||||
<p>The following categories of goods and services are prohibited from being listed and sold on the site:</p>
|
||||
<ul>
|
||||
<li>6.4.1. Weapons, ammunition, military equipment, spare parts, components and instruments thereof, explosives, detonation devices, all types of rocket fuel, as well as special materials and special equipment for their production, special equipment of paramilitary organizations, and technical documentation for their production and operation.</li>
|
||||
<li>6.4.2. Rocket and space complexes, military communications and control systems, and technical documentation for their production and operation.</li>
|
||||
<li>6.4.3. Chemical warfare agents, protective equipment against them, and technical documentation for their production and use.</li>
|
||||
<li>6.4.4. Results of research and design work, as well as fundamental exploratory research on the creation of weapons and military equipment.</li>
|
||||
<li>6.4.5. Services, works and materials related to military service and paramilitary activities.</li>
|
||||
<li>6.4.6. Any weapons, including hunting, civilian and other types, as well as components thereof, knives (except kitchen, penknives and stationery knives).</li>
|
||||
<li>6.4.7. Radioactive substances and isotopes, uranium and other fissile materials and products made from them.</li>
|
||||
<li>6.4.8. Radioactive material waste.</li>
|
||||
<li>6.4.9. Precious and rare-earth metals, precious stones, as well as waste containing precious and rare-earth metals and precious stones.</li>
|
||||
<li>6.4.10. X-ray equipment, instruments and equipment using radioactive substances and isotopes.</li>
|
||||
<li>6.4.11. Poisons, narcotic drugs and psychotropic substances, and their precursors.</li>
|
||||
<li>6.4.12. Ethyl alcohol, alcoholic beverages.</li>
|
||||
<li>6.4.13. Prescription medicines, as well as narcotic, psychotropic and alcohol-containing (with a volume fraction of ethyl alcohol exceeding 25%) medicines and spirit-based balms.</li>
|
||||
<li>6.4.14. Medicinal raw materials obtained from reindeer husbandry (antlers and endocrine raw materials).</li>
|
||||
<li>6.4.15. Tobacco products or vaping products.</li>
|
||||
<li>6.4.16. Encryption equipment and technical documentation for its production and use.</li>
|
||||
<li>6.4.17. Counterfeit banknotes.</li>
|
||||
<li>6.4.18. Foreign currency and other currency valuables, coins and banknotes of the Russian Federation in circulation.</li>
|
||||
<li>6.4.19. Radio-electronic and special technical means designed for covert acquisition of information, as well as high-frequency devices consisting of one or more radio transmitting devices and (or) their combinations and auxiliary equipment designed for transmitting and receiving radio waves at a frequency above 8 GHz.</li>
|
||||
<li>6.4.20. Materials and services that violate the privacy of private life, encroach on the honor, dignity and business reputation of citizens and legal entities, as well as containing state, banking, commercial and other secrets.</li>
|
||||
<li>6.4.21. State awards of the Russian Federation, RSFSR, USSR, as well as copies thereof.</li>
|
||||
<li>6.4.22. State identity documents, badges, passes, permits, certificates, travel documents and licenses, as well as other documents granting rights or exempting from rights or obligations, blank forms for these documents, as well as services for obtaining them.</li>
|
||||
<li>6.4.23. Cultural heritage objects of the peoples of the Russian Federation, as well as archaeological heritage objects.</li>
|
||||
<li>6.4.24. Human organs and tissues, as well as donor services.</li>
|
||||
<li>6.4.25. Animals and plants listed in the Red Book of the Russian Federation and the Red Books of the constituent entities of the Russian Federation, parts and organs of animals listed in the Red Book of the Russian Federation and the Red Books of the constituent entities of the Russian Federation, as well as animals and plants protected by international treaties of the Russian Federation.</li>
|
||||
<li>6.4.26. Skins and products made from skins of rare and endangered animal species in accordance with the current legislation of the Russian Federation.</li>
|
||||
<li>6.4.27. Fishing nets, materials for their manufacture, as well as services for their manufacture, electric fishing rods and traps prohibited for sale on the territory of the Russian Federation.</li>
|
||||
<li>6.4.28. Extremist materials, materials calling for mass riots, terrorist and extremist activities, participation in mass public events, incitement of interethnic and interfaith discord.</li>
|
||||
<li>6.4.29. Items with Nazi symbols or symbols of organizations banned in the Russian Federation.</li>
|
||||
<li>6.4.30. Counterfeit or stolen products or property.</li>
|
||||
<li>6.4.31. Databases, including those containing personal data, that may facilitate unauthorized mailings.</li>
|
||||
<li>6.4.32. Materials transmitted exclusively virtually and not recorded on any tangible medium (ideas, methods, principles, etc.).</li>
|
||||
<li>6.4.33. Gaming equipment used for gambling, lottery equipment, provision of services for accepting bets for participation in online gambling, acceptance of payments for lottery tickets, receipts and other documents certifying the right to participate in a lottery, as well as the sale of virtual currency.</li>
|
||||
<li>6.4.34. Vehicle documents, state license plates for vehicles.</li>
|
||||
<li>6.4.35. Goods whose circulation violates the intellectual property rights of third parties (including patents, trademarks, copyrights, etc.).</li>
|
||||
<li>6.4.36. Investment services, transactions with monetary funds and cryptocurrencies, as well as goods and services whose acquisition or use is guaranteed to generate earnings or profit.</li>
|
||||
<li>6.4.37. Goods and services sold by multilevel network marketing organizations whose activities are based on the creation of a network of independent distributors or sales agents.</li>
|
||||
<li>6.4.38. Services and (or) work of an intimate, erotic or sexual nature, as well as pornographic or erotic materials.</li>
|
||||
<li>6.4.39. Goods or services whose use may be aimed at violating the current legislation of the Russian Federation.</li>
|
||||
<li>6.4.40. Non-existent goods or services, as well as goods or services that have no consumer value.</li>
|
||||
<li>6.4.41. Transcendental services and alternative medicine services.</li>
|
||||
<li>6.4.42. Services for replacing licensed software or disrupting the operation of technical protection means installed by the rights holder on phones, smartphones, laptops, navigators, personal computers, etc.</li>
|
||||
<li>6.4.43. Other goods or services whose circulation is prohibited or restricted under the legislation of the Russian Federation, as well as those capable of having a negative impact on the business reputation of international payment systems.</li>
|
||||
<li>6.4.44. Injectable preparations and solutions, as well as substances used for their manufacture.</li>
|
||||
<li>6.4.45. Services, works and materials related to the activities of occult organizations and sects.</li>
|
||||
<li>6.4.46. Goods and services sold by companies organized in the form of financial pyramids.</li>
|
||||
<li>6.4.47. Antiques.</li>
|
||||
<li>6.4.48. Biologically active additives (dietary supplements). Sale of dietary supplements is permitted only through pharmacy institutions (pharmacies, pharmacy stores, pharmacy kiosks), specialized stores with dietary products, and grocery stores with special departments and sections.</li>
|
||||
<li>6.4.49. Custom term papers and diplomas.</li>
|
||||
<li>6.4.50. Anonymous work (drug couriers, etc.).</li>
|
||||
<li>6.4.51. Copies and replicas of original goods.</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section class="legal-section">
|
||||
|
||||
@@ -1,5 +1,521 @@
|
||||
<div class="legal-page">
|
||||
<div class="legal-container">
|
||||
<h1>Հdelays DELAYS ՀԱՄDELAYS</h1>
|
||||
<h1>ՀԱՆՐԱՅԻՆ ՕՖԵՐՏԱՅԻ ՀԱՄԱՁԱՅՆԱԳԻՐ</h1>
|
||||
|
||||
<section class="legal-section">
|
||||
<h2>Հիմնական հասկացություններ</h2>
|
||||
|
||||
<p>Սույն փաստաթղթում ներկայացվում են հանրային օֆերտայի համաձայնագրում կիրառվող հիմնական տերմիններն ու բացատրությունները.</p>
|
||||
|
||||
<ul>
|
||||
<li><strong>Մարկետփլեյս, ինտերնետ-կայք կամ Կայք</strong> - տեխնիկական և ծրագրային միջոցների համալիր, որը նախատեսված է https://dexarmarket.ru հասցեում գործող վեբ-ռեսուրսի աշխատանքի համար: Կայքը պատկանում է սեփականատիրոջը և ծառայում է որպես հարթակ անկախ վաճառողների և գնորդների փոխգործակցության կազմակերպման համար: Կայքի սեփականատերն ինքնուրույն չի զբաղվում ապրանքների և ծառայությունների վաճառքով, այլ տրամադրում է տարածք հայտարարությունների տեղադրման և գործարքների կնքման համար:</li>
|
||||
|
||||
<li><strong>Օգտատեր</strong> - ֆիզիկական անձ, որը օգտվում է կայքից, գրանցվում է և ընդունում է սույն համաձայնագրի պայմանները:</li>
|
||||
|
||||
<li><strong>Անձնական հաշիվ</strong> - Օգտատիրոջ անհատական էջը, որը պաշտպանված է անհատական գրանցման տվյալներով (մուտքանուն և գաղտնաբառ): Մուտքանուն կարող է լինել էլեկտրոնային փոստի հասցեն կամ բջջային հեռախոսահամարը, որն օգտագործվում է նույնականացման համար:</li>
|
||||
|
||||
<li><strong>Հաշվառման տվյալներ</strong> - օգտատիրոջ անվան (մուտքանուն) և գաղտնաբառի համակցություն, որը ստեղծվում է գրանցման ընթացքում:</li>
|
||||
|
||||
<li><strong>Գնորդ</strong> - գրանցված Օգտատեր, որը պատվեր է կատարել կայքի միջոցով:</li>
|
||||
|
||||
<li><strong>Ադմինիստրատոր կամ Կայքի սեփականատեր</strong> - «ԻՆՏ ՖԻՆ ԼՈԳԻՍՏԻԿ» ՍՊԸ (ՀՎՀՀ 9909697628) և «ԻՆՏ ՖԱԿՏՈՐԻՆԳ» ՍՊԸ (ՀՎՀՀ 9909697635):</li>
|
||||
|
||||
<li><strong>Վաճառող կամ Սելլեր</strong> - ֆիզիկական կամ իրավաբանական անձինք, ձեռնարկատերեր, որոնք ռեսուրսում առաջարկում են ապրանքներ և ծառայություններ: Վաճառողները անձամբ պատասխանատվություն են կրում ապրանքների որակի, անվտանգության և նկարագրությանը համապատասխանության համար:</li>
|
||||
|
||||
<li><strong>Կայքի բովանդակություն</strong> - ռեսուրսում տեղակայված նյութերի ամբողջություն, ներառյալ դիզայնը, տեքստերը, գրաֆիկան, տեսանյութերը, աուդիոնյութերը և այլ օբյեկտներ:</li>
|
||||
|
||||
<li><strong>Ապրանք</strong> - նյութական և թվային արտադրանք, ինչպես նաև ծառայություններ, որոնք առաջարկվում են վաճառքի կայքի միջոցով:</li>
|
||||
|
||||
<li><strong>Թվային ապրանք</strong> - ապրանքներ, որոնք տարածվում են էլեկտրոնային ձևով, օրինակ` ծրագրային ապահովում, առցանց դասընթացների բաժանորդագրություն, վիրտուալ ակտիվներ, երաժշտական թրեքեր, էլեկտրոնային գրքեր և նմանատիպ արտադրանք:</li>
|
||||
|
||||
<li><strong>Պատվեր</strong> - Գնորդի կողմից ապրանքներ կամ ծառայություններ ձեռք բերելու ձևակերպված հայտ:</li>
|
||||
|
||||
<li><strong>Սերվիս</strong> - ռեսուրսում ինտեգրված հատուկ ծրագրային ապահովում, որը հնարավորություն է տալիս օգտվել կայքի ֆունկցիոնալությունից:</li>
|
||||
|
||||
<li><strong>Կայքի սեփականատիրոջ պրոդուկտներ</strong> - տեղեկատվական և ուղեկցող ծառայություններ, որոնք տրամադրվում են կայքի սեփականատիրոջ կողմից:</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section class="legal-section">
|
||||
<h2>1. Ընդհանուր դրույթներ</h2>
|
||||
|
||||
<p>1.1. Սույն փաստաթուղթը սահմանում է ադմինիստրատորին պատկանող ռեսուրսների օգտագործման կարգը, ներառյալ կայքը, բջջային տարբերակները և հավելվածները, որոնք կառավարվում են Ադմինիստրացիայի կողմից:</p>
|
||||
|
||||
<p>1.2. Փաստաթուղթը հանդիսանում է Օգտատիրոջ և ռեսուրսի Սեփականատիրոջ միջև պարտադիր համաձայնագիր:</p>
|
||||
|
||||
<p>1.3. Սույն համաձայնագիրը և կայքում տեղադրված պրոդուկտների մասին տեղեկատվությունը համապատասխանում են հանրային օֆերտայի սահմանմանը` համաձայն ՌԴ քաղաքացիական օրենսգրքի 435-րդ հոդվածի և 437-րդ հոդվածի 2-րդ կետի:</p>
|
||||
|
||||
<p>1.4. Օգտատերը համաձայնում է պայմանագրի պայմաններին ինքնաբերաբար` սկսած կայք առաջին մուտքից, գրանցումից կամ առանց նույնականացման պատվերի ձևակերպումից, «Պատվիրել», «Ուղարկել հաղորդագրություն» կամ «Գնել» կոճակները սեղմելուց:</p>
|
||||
|
||||
<p>1.5. Օֆերտայի ակցեպտով համաձայնագրի կնքումը կողմերի ստորագրություն չի պահանջում և ճանաչվում է որպես վավեր էլեկտրոնային ձևով:</p>
|
||||
|
||||
<p>1.6. Կայքի օգտագործումը ենթադրում է համաձայնություն համաձայնագրի պայմաններին, որը ուժի մեջ է մտնում օգտատիրոջ կողմից համաձայնությունն արտահայտելուց անմիջապես հետո:</p>
|
||||
|
||||
<p>1.7. Եթե Օգտատերը համաձայն չէ պայմաններին, նա պարտավորվում է անհապաղ դադարեցնել ռեսուրսից օգտվելը:</p>
|
||||
|
||||
<p>1.8. Կայքի օգտագործման լրացուցիչ կարգավորումը իրականացվում է <a [routerLink]="'/privacy-policy' | langRoute">Անձնական տվյալների մշակման քաղաքականությամբ</a>:</p>
|
||||
|
||||
<p>1.9. Համաձայնագրում փոփոխություններ կարող են կատարվել Սեփականատիրոջ կողմից առանց նախնական ծանուցման և դառնում են պարտադիր փոփոխությունների հրապարակման պահից:</p>
|
||||
|
||||
<p>1.10. Գովազդային արշավների ընթացքում կարող են սահմանվել պատվերի ձևակերպման, վերադարձի կամ ապրանքների փոխանակման հատուկ պայմաններ:</p>
|
||||
|
||||
<p>1.14. Օֆերտան նախատեսված է ռեսուրսի բոլոր օգտատերերի համար, ներառյալ իրավաբանական անձինք և անհատ ձեռնարկատերերը:</p>
|
||||
</section>
|
||||
|
||||
<section class="legal-section">
|
||||
<h2>2. Համաձայնագրի առարկան</h2>
|
||||
|
||||
<p>2.1. Համաձայնագրի նպատակը Օգտատերերին հնարավորություն տալն է ձեռք բերել ռեսուրսում ներկայացված ապրանքներ և ծառայություններ, ինչպես նաև օգտվել Կայքի սեփականատիրոջ կողմից տրամադրվող պրոդուկտներից:</p>
|
||||
|
||||
<p>2.2. Համաձայնագիրը կարգավորում է կայքի և Սեփականատիրոջ կողմից տրամադրվող գործառույթների օգտագործման կարգը:</p>
|
||||
|
||||
<p>2.3. Փաստաթղթի գործողությունը տարածվում է կայքում առկա ապրանքների, ծառայությունների և պրոդուկտների բոլոր տեսակների վրա:</p>
|
||||
</section>
|
||||
|
||||
<section class="legal-section">
|
||||
<h2>3. Ապրանքների վաճառքի և ծառայությունների մատուցման պայմաններ</h2>
|
||||
|
||||
<p><strong>3.1. Վաճառքի պայմանների ընդունում</strong></p>
|
||||
<p>Օգտատերը, մարկետփլեյսի միջոցով պատվերներ կատարելով, արտահայտում է լիակատար համաձայնություն ապրանքների վաճառքի և ծառայությունների մատուցման պայմաններին, որոնք սահմանված են սույն համաձայնագրով:</p>
|
||||
|
||||
<p><strong>3.2. Պայմանագրերի կնքում</strong></p>
|
||||
<p>Մանրածախ առուվաճառքի պայմանագիրը կամ ծառայությունների մատուցման պայմանագիրը կնքվում է անմիջապես Վաճառողի և Գնորդի միջև` Վաճառողի կողմից վճարումը հաստատող դրամարկղային կամ ապրանքային կտրոններ տրամադրելու պահից: Մարկետփլեյսը կատարում է տեղեկատվական միջնորդի դեր, տրամադրում է ենթակառուցվածք գործարքների կատարման համար, բայց չի հանդիսանում այդ պայմանագրի կողմ: Պայմանագրի կատարման, ապրանքների և ծառայությունների որակի համար պատասխանատվությունը կրում է Վաճառողը:</p>
|
||||
|
||||
<p><strong>3.3. Համաձայնություն կոնտակտների մշակմանը</strong></p>
|
||||
<p>Օգտատերը համաձայնություն է տալիս իր կոնտակտային տվյալների (էլեկտրոնային փոստի հասցե, հեռախոսահամար) օգտագործմանը կայքի ադմինիստրացիայի, Վաճառողի և ներգրավված երրորդ կողմերի կողմից Գնորդի նկատմամբ պարտավորությունների կատարման համար, ներառյալ գովազդային և այլ տեղեկատվության ուղարկումը:</p>
|
||||
|
||||
<p><strong>3.4. Երրորդ անձանց ներգրավում</strong></p>
|
||||
<p>Օգտատերը համաձայնում է, որ Վաճառողը կարող է երրորդ անձանց ներգրավել առուվաճառքի կամ ծառայությունների մատուցման պայմանագրի կատարման համար, միաժամանակ Վաճառողի պատասխանատվությունը պարտավորությունների կատարման համար պահպանվում է:</p>
|
||||
|
||||
<p><strong>3.5. Պայմանագրերից բխող իրավունքներ և պարտավորություններ</strong></p>
|
||||
<p>Առուվաճառքի պայմանագրերից բխող իրավունքներն ու պարտավորությունները ծագում են անմիջապես Վաճառողի մոտ: Օգտատերը գիտակցում է, որ Կայքի սեփականատերը կատարում է մարկետփլեյսի օպերատորի դեր և պատասխանատվություն չի կրում Վաճառողների գործողությունների, ապրանքների որակի, Վաճառողի կողմից գործարքներ իրականացնելու իրավական հիմքերի կամ պարտավորությունների փաստացի կատարման համար:</p>
|
||||
|
||||
<p><strong>3.6. Կայքի սեփականատիրոջ գործառույթները</strong></p>
|
||||
<p>Կայքի սեփականատերը տրամադրում է տեղեկատվական և տեխնիկական ուղեկցում. համակարգում է Գնորդի և Վաճառողի միջև փոխգործակցությունը, փոխանցում է պատվերի մասին տեղեկատվությունը, կարող է աջակցել վեճերի կարգավորմանը: Այնուամենայնիվ, պայմանագրի կատարման պատասխանատվությունը մնում է Վաճառողի վրա:</p>
|
||||
|
||||
<p><strong>3.7. Վաճառողի կողմից իրավունքների փոխանցում</strong></p>
|
||||
<p>Գնորդը տեղեկացված է և համաձայնում է, որ Վաճառողը կարող է զիջել կամ փոխանցել իր իրավունքներն ու պարտավորությունները երրորդ անձանց:</p>
|
||||
|
||||
<p><strong>3.8. Օրենքների կիրառություն</strong></p>
|
||||
<p>Օգտատիրոջ և Վաճառողի միջև հարաբերությունները կարգավորվում են «Սպառողների իրավունքների պաշտպանության մասին» դաշնային օրենքի (թիվ 2300-1, 07 փետրվարի 1992 թ.) և ՌԴ քաղաքացիական օրենսգրքի դրույթներով:</p>
|
||||
|
||||
<p><strong>3.10. Գովազդային հաղորդագրություններ</strong></p>
|
||||
<p>Օգտատերը համաձայնություն է տալիս գովազդային հաղորդագրություններ ստանալուն` «Գովազդի մասին» դաշնային օրենքին համապատասխան:</p>
|
||||
</section>
|
||||
|
||||
<section class="legal-section">
|
||||
<h2>4. Կայքում գրանցում և Օգտատիրոջ անձնական հաշիվ</h2>
|
||||
|
||||
<p><strong>4.1. Գրանցման ընթացակարգեր</strong></p>
|
||||
<p>Օգտատիրոջը առաջարկվում է գրանցվել կայքում` առանձին գործառույթներից և սերվիսներից լիարժեք օգտվելու համար: Թեև գրանցումը պարտադիր չէ պատվեր ձևակերպելու համար, այն ստեղծում է լրացուցիչ հնարավորություններ, ներառյալ մուտք դեպի Անձնական հաշիվ:</p>
|
||||
|
||||
<p><strong>4.2. Օգտատիրոջ պարտավորությունները գրանցման ժամանակ</strong></p>
|
||||
<p>Գրանցվելիս Օգտատերը պարտավորվում է տրամադրել ճշգրիտ և արդիական տեղեկատվություն` լրացնելով գրանցման հայտը: Անհրաժեշտ է պահպանել տվյալների արդիականությունը:</p>
|
||||
|
||||
<p><strong>4.3. Օգտատիրոջ նույնականացում</strong></p>
|
||||
<p>Անհատական մուտքանվան և գաղտնաբառի օգտագործմամբ կատարված ցանկացած գործողություն համարվում է հենց Օգտատիրոջ գործողություն, քանի դեռ հակառակը չի ապացուցվել:</p>
|
||||
|
||||
<p><strong>4.4. Հաշվառման տվյալների գաղտնիություն</strong></p>
|
||||
<p>Օգտատերը պարտավորվում է գաղտնի պահել գրանցման ընթացքում տրամադրված մուտքանունն ու գաղտնաբառը: Անվտանգության խախտման կասկածի դեպքում անհրաժեշտ է անհապաղ տեղեկացնել կայքի ադմինիստրացիային` ուղարկելով նամակ <a href="mailto:info@dexarmarket.ru">info@dexarmarket.ru</a> հասցեին:</p>
|
||||
|
||||
<p><strong>4.7. Տվյալների հաստատում</strong></p>
|
||||
<p>Կայքի սեփականատերը իրավունք ունի ցանկացած պահի պահանջել տրամադրված տեղեկատվության հաստատում:</p>
|
||||
|
||||
<p><strong>4.11. Աշխատանքային սեսիայի ավարտ</strong></p>
|
||||
<p>Օգտատերը պարտավոր է ինքնուրույն ավարտել աշխատանքը Անձնական հաշվում («Ելք»)` լքելով կայքը, իր հաշվի անվտանգությունն ապահովելու համար:</p>
|
||||
</section>
|
||||
|
||||
<section class="legal-section">
|
||||
<h2>5. Կայքի սեփականատիրոջ իրավունքներն ու պարտավորությունները</h2>
|
||||
|
||||
<p><strong>5.1. Կայքի սեփականատիրոջ իրավունքները</strong></p>
|
||||
<p>Կայքի սեփականատերը օժտված է հետևյալ լիազորություններով.</p>
|
||||
<ul>
|
||||
<li>Սահմանել ռեսուրսի օգտագործման սահմանափակումներ բոլոր կամ առանձին խմբերի օգտատերերի համար:</li>
|
||||
<li>Օգտատերերին տեղեկություններ ուղարկել կայքում նորարարությունների և փոփոխությունների մասին:</li>
|
||||
<li>Առանց Գնորդի նախնական համաձայնության փոխել ապրանքների մատակարարին և/կամ առաքող ընկերությանը:</li>
|
||||
<li>Միակողմանի կարգով փոխել անցկացվող ակցիաների պայմանները:</li>
|
||||
<li>Սահմանափակել այն Օգտատերերի գործողությունները, որոնք ռիսկեր են ստեղծում կայքի աշխատունակության համար:</li>
|
||||
<li>Տեխնիկական աշխատանքներ իրականացնել առանց օգտատերերին նախապես զգուշացնելու:</li>
|
||||
<li>Կայքում հավաքված վիճակագրությունն օգտագործել սեփական նպատակների համար:</li>
|
||||
<li>Ցանկացած պահի փոխել ապրանքների և ծառայությունների ցանկը, գները և պայմանները:</li>
|
||||
<li>Մերժել սպասարկումը այն Օգտատերերին, որոնց նկատմամբ կան իրավախախտ գործողությունների կասկածներ:</li>
|
||||
</ul>
|
||||
|
||||
<p><strong>5.2. Կայքի սեփականատիրոջ պարտավորությունները</strong></p>
|
||||
<p>Կայքի սեփականատիրոջ հիմնական պարտականությունն է Օգտատերերին մատուցել սույն համաձայնագրի 2.1 կետով նախատեսված ծառայությունները:</p>
|
||||
</section>
|
||||
|
||||
<section class="legal-section">
|
||||
<h2>6. Օգտատիրոջ իրավունքներն ու պարտավորությունները</h2>
|
||||
|
||||
<p><strong>6.1. Օգտատիրոջ պարտավորությունները</strong></p>
|
||||
<p>Օգտատերը պարտավորվում է պահպանել մի շարք կարևոր պարտականություններ.</p>
|
||||
<ul>
|
||||
<li>Ծանոթանալ համաձայնագրի տեքստին մինչև առուվաճառքի կամ ծառայությունների մատուցման պայմանագիր կնքելը:</li>
|
||||
<li>Պահպանել էթիկական վարքագիծ կարծիքներ գրելիս և կայքի անձնակազմի հետ շփվելիս:</li>
|
||||
<li>Շփվել քաղաքավարի և հարգալից աշխատակիցների և գործընկերների հետ:</li>
|
||||
<li>Չթույլատրել հայհոյանքների, կոպտության և վիրավորանքների տարածում:</li>
|
||||
<li>Չստեղծել խոչընդոտներ կայքի և դրա սերվիսների բնականոն աշխատանքի համար:</li>
|
||||
<li>Չզբաղվել վիրուսների, վնասակար ծրագրերի և այլ վտանգավոր ֆայլերի բեռնմամբ:</li>
|
||||
<li>Առանց Ադմինիստրացիայի թույլտվության չօգտագործել տեղեկատվություն հավաքելու արգելված ավտոմատացված ծրագրեր:</li>
|
||||
<li>Չփորձել մուտք գործել այլ անձանց հաշվառման տվյալներին:</li>
|
||||
<li>Օրինական կերպով օգտագործել կայքի բովանդակությունը և խուսափել նյութերի անօրինական պատճենումից:</li>
|
||||
<li>Գրանցվել միայն սեփական անունից և չներկայանալ որպես այլ անձ:</li>
|
||||
<li>Ժամանակին վճարել պատվիրված ապրանքների և ծառայությունների համար` համաձայն համաձայնագրի:</li>
|
||||
<li>Ձեռք բերված ապրանքներն օգտագործել բացառապես անձնական կարիքների համար` առանց առևտրային նպատակների:</li>
|
||||
<li>Պահպանել ռեսուրսի տեղեկատվական անվտանգությունը` զերծ մնալով կայքը կոտրելու կամ դրա ամբողջականությունը խախտելու փորձերից:</li>
|
||||
</ul>
|
||||
|
||||
<p><strong>6.2. Օգտատիրոջ արգելված գործողությունները</strong></p>
|
||||
<p>Օգտատիրոջը խստիվ արգելվում է.</p>
|
||||
<ul>
|
||||
<li>Բեռնել և հրապարակել օրենքին հակասող, վիրուսային ծրագրեր, կեղծ տեղեկատվություն կամ նվաստացուցիչ քննադատություն պարունակող բովանդակություն:</li>
|
||||
<li>Խախտել այլ օգտատերերի իրավունքները և վնաս պատճառել անչափահաս քաղաքացիներին:</li>
|
||||
<li>Ցանկացած վարքագիծ, որը խախտում է ռուսական օրենսդրությունը, ներառյալ միջազգային իրավունքի նորմերը:</li>
|
||||
</ul>
|
||||
|
||||
<p><strong>6.3. Օգտատիրոջ իրավունքները</strong></p>
|
||||
<p>Օգտատերն իրավունք ունի հրաժարվել գովազդային հաղորդագրություններ ստանալուց` օգտվելով կայքում համապատասխան գործիքից կամ ուղարկելով հարցում <a href="mailto:info@dexarmarket.ru">info@dexarmarket.ru</a> էլեկտրոնային փոստին կամ նամակով Կայքի սեփականատիրոջ պաշտոնական հասցեին:</p>
|
||||
|
||||
<p><strong>6.4. Կայքում վաճառքի համար արգելված ապրանքներ</strong></p>
|
||||
<p>Կայքում արգելվում է տեղադրել և վաճառել հետևյալ կատեգորիայի ապրանքներն ու ծառայությունները.</p>
|
||||
<ul>
|
||||
<li>6.4.1. Զենք, զինամթերք, ռազմական տեխնիկա, պահեստամասեր, համալրիչներ և սարքեր դրանց համար, պայթուցիկ նյութեր, պայթեցման միջոցներ, հրթիռային վառելիքի բոլոր տեսակները, ինչպես նաև հատուկ նյութեր և հատուկ սարքավորումներ դրանց արտադրության համար, ռազմականացված կազմակերպությունների հատուկ հանդերձանք և դրանց արտադրության ու շահագործման նորմատիվ-տեխնիկական արտադրանք:</li>
|
||||
<li>6.4.2. Հրթիռատիեզերական համալիրներ, ռազմական նշանակության կապի և կառավարման համակարգեր, ինչպես նաև դրանց արտադրության և շահագործման նորմատիվ-տեխնիկական փաստաթղթեր:</li>
|
||||
<li>6.4.3. Մարտական թունավոր նյութեր, դրանցից պաշտպանվելու միջոցներ և դրանց արտադրության ու օգտագործման նորմատիվ-տեխնիկական փաստաթղթեր:</li>
|
||||
<li>6.4.4. Զենքի և ռազմական տեխնիկայի ստեղծմանն ուղղված գիտահետազոտական և նախագծային աշխատանքների արդյունքներ, ինչպես նաև հիմնարար հետազոտություններ:</li>
|
||||
<li>6.4.5. Ծառայություններ, աշխատանքներ և նյութեր, որոնք կապված են զինվորական ծառայության և ռազմականացված գործունեության իրականացման հետ:</li>
|
||||
<li>6.4.6. Ցանկացած զենք, ներառյալ որսորդական, քաղաքացիական և այլ տեսակներ, ինչպես նաև դրա համալրիչներ, դանակներ (բացառությամբ խոհանոցային, գրպանի և գրասենյակային դանակների):</li>
|
||||
<li>6.4.7. Ռադիոակտիվ նյութեր և իզոտոպներ, ուրան և այլ բաժանվող նյութեր ու դրանցից պատրաստված արտադրանք:</li>
|
||||
<li>6.4.8. Ռադիոակտիվ նյութերի թափոններ:</li>
|
||||
<li>6.4.9. Թանկարժեք և հազվագյուտ հողային մետաղներ, թանկարժեք քարեր, ինչպես նաև թանկարժեք և հազվագյուտ հողային մետաղներ ու թանկարժեք քարեր պարունակող թափոններ:</li>
|
||||
<li>6.4.10. Ռենտգենյան սարքավորում, սարքեր և սարքավորումներ, որոնք օգտագործում են ռադիոակտիվ նյութեր և իզոտոպներ:</li>
|
||||
<li>6.4.11. Թույներ, թմրամիջոցներ և հոգեմետ նյութեր, ինչպես նաև դրանց պրեկուրսորներ:</li>
|
||||
<li>6.4.12. Էթիլային սպիրտ, ալկոհոլային խմիչքներ:</li>
|
||||
<li>6.4.13. Դեղատոմսով տրվող դեղամիջոցներ, ինչպես նաև թմրամիջոց պարունակող, հոգեմետ և սպիրտ պարունակող (էթիլային սպիրտի ծավալային բաժինը 25%-ից ավելի) դեղամիջոցներ և սպիրտային հիմքով բալզամներ:</li>
|
||||
<li>6.4.14. Հյուսիսային եղջերուաբուծությունից ստացվող դեղագործական հումք (եղջյուրներ և էնդոկրին հումք):</li>
|
||||
<li>6.4.15. Ծխախոտային արտադրանք կամ վեյփինգի ապրանքներ:</li>
|
||||
<li>6.4.16. Գաղտնագրման տեխնիկա և դրա արտադրության ու օգտագործման նորմատիվ-տեխնիկական փաստաթղթեր:</li>
|
||||
<li>6.4.17. Կեղծ դրամանիշներ:</li>
|
||||
<li>6.4.18. Արտարժույթ և այլ արժութային արժեքներ, ինչպես նաև շրջանառության մեջ գտնվող Ռուսաստանի Դաշնության մետաղադրամներ և թղթադրամներ:</li>
|
||||
<li>6.4.19. Ռադիոէլեկտրոնային և հատուկ տեխնիկական միջոցներ, որոնք նախատեսված են տեղեկատվությունը գաղտնի ստանալու համար, ինչպես նաև բարձր հաճախականության սարքեր, որոնք կազմված են մեկ կամ մի քանի ռադիոհաղորդիչ սարքերից և (կամ) դրանց համակցություններից ու օժանդակ սարքավորումից, և նախատեսված են 8 ԳՀց-ից բարձր հաճախականությամբ ռադիոալիքների փոխանցման և ընդունման համար:</li>
|
||||
<li>6.4.20. Նյութեր և ծառայություններ, որոնք խախտում են անձնական կյանքի գաղտնիությունը, ոտնահարում են քաղաքացիների և իրավաբանական անձանց պատիվը, արժանապատվությունն ու գործարար համբավը, ինչպես նաև պարունակում են պետական, բանկային, առևտրային կամ այլ գաղտնիքներ:</li>
|
||||
<li>6.4.21. ՌԴ, ՌԽՖՍՀ, ԽՍՀՄ պետական պարգևներ, ինչպես նաև դրանց պատճենները:</li>
|
||||
<li>6.4.22. Պետական ինքնությունը հաստատող փաստաթղթեր, նշաններ, անցագրեր, թույլտվություններ, հավաստագրեր, ճանապարհորդական փաստաթղթեր և լիցենզիաներ, ինչպես նաև այլ փաստաթղթեր, որոնք իրավունքներ են տրամադրում կամ ազատում են իրավունքներից կամ պարտականություններից, այդ փաստաթղթերի բլանկներ, ինչպես նաև դրանք ստանալու ծառայություններ:</li>
|
||||
<li>6.4.23. Ռուսաստանի Դաշնության ժողովուրդների մշակութային ժառանգության օբյեկտներ, ինչպես նաև հնագիտական ժառանգության օբյեկտներ:</li>
|
||||
<li>6.4.24. Մարդու օրգաններ և հյուսվածքներ, ինչպես նաև դոնորական ծառայություններ:</li>
|
||||
<li>6.4.25. Կենդանիներ և բույսեր, որոնք ներառված են Ռուսաստանի Դաշնության և դրա սուբյեկտների Կարմիր գրքերում, այդ կենդանիների մասեր և օրգաններ, ինչպես նաև կենդանիներ և բույսեր, որոնք պաշտպանվում են Ռուսաստանի Դաշնության միջազգային պայմանագրերով:</li>
|
||||
<li>6.4.26. Հազվագյուտ և վերացման վտանգի տակ գտնվող կենդանիների տեսակների կաշվից պատրաստված կաշիներ և արտադրանք` Ռուսաստանի Դաշնության գործող օրենսդրությանը համապատասխան:</li>
|
||||
<li>6.4.27. Ձկնորսական ցանցեր, դրանց պատրաստման նյութեր, ինչպես նաև դրանց պատրաստման ծառայություններ, էլեկտրաձկնորսական սարքեր և թակարդներ, որոնց վաճառքը արգելված է Ռուսաստանի Դաշնության տարածքում:</li>
|
||||
<li>6.4.28. Ծայրահեղական նյութեր, նյութեր, որոնք կոչ են անում զանգվածային անկարգությունների, ահաբեկչական և ծայրահեղական գործունեության, զանգվածային հանրային միջոցառումներին մասնակցելու, ազգամիջյան և միջկրոնական թշնամանքի հրահրման:</li>
|
||||
<li>6.4.29. Նացիստական խորհրդանիշներ կամ Ռուսաստանի Դաշնությունում արգելված կազմակերպությունների խորհրդանիշներ պարունակող առարկաներ:</li>
|
||||
<li>6.4.30. Կոնտրաֆակտ կամ գողացված արտադրանք կամ գույք:</li>
|
||||
<li>6.4.31. Տվյալների բազաներ, ներառյալ անձնական տվյալներ պարունակող բազաները, որոնք կարող են նպաստել չարտոնված զանգվածային ուղարկումներին:</li>
|
||||
<li>6.4.32. Նյութեր, որոնք փոխանցվում են բացառապես վիրտուալ ձևով և գրանցված չեն որևէ նյութական կրիչի վրա (գաղափարներ, մեթոդներ, սկզբունքներ և այլն):</li>
|
||||
<li>6.4.33. Խաղային սարքավորում, որն օգտագործվում է ազարտային խաղերի անցկացման համար, վիճակախաղային սարքավորում, ինտերնետում ազարտային խաղերին մասնակցելու համար խաղադրույքներ ընդունելու ծառայություններ, վիճակախաղի տոմսերի համար վճարումների ընդունում, անդորրագրեր և այլ փաստաթղթեր, որոնք հավաստում են վիճակախաղին մասնակցելու իրավունքը, ինչպես նաև վիրտուալ արժույթի վաճառք:</li>
|
||||
<li>6.4.34. Տրանսպորտային միջոցների փաստաթղթեր, տրանսպորտային միջոցների պետական համարանիշներ:</li>
|
||||
<li>6.4.35. Ապրանքներ, որոնց շրջանառությունը խախտում է երրորդ անձանց մտավոր սեփականության իրավունքները (ներառյալ արտոնագրեր, ապրանքային նշաններ, հեղինակային իրավունքներ և այլն):</li>
|
||||
<li>6.4.36. Ներդրումային ծառայություններ, դրամական միջոցների և կրիպտոարժույթների հետ գործառնություններ, ինչպես նաև ապրանքներ և ծառայություններ, որոնց ձեռքբերումը կամ օգտագործումը երաշխավորված եկամուտ կամ շահույթ է խոստանում:</li>
|
||||
<li>6.4.37. Բազմամակարդակ ցանցային մարքեթինգի կազմակերպությունների կողմից իրացվող ապրանքներ և ծառայություններ, որոնց գործունեությունը հիմնված է անկախ դիստրիբյուտորների կամ վաճառքի գործակալների ցանց ստեղծելու վրա:</li>
|
||||
<li>6.4.38. Ինտիմ, էրոտիկ կամ սեռական բնույթի ծառայություններ և (կամ) աշխատանքներ, ինչպես նաև պոռնոգրաֆիկ կամ էրոտիկ նյութեր:</li>
|
||||
<li>6.4.39. Ապրանքներ կամ ծառայություններ, որոնց օգտագործումը կարող է ուղղված լինել Ռուսաստանի Դաշնության գործող օրենսդրության խախտմանը:</li>
|
||||
<li>6.4.40. Չգոյություն ունեցող ապրանքներ կամ ծառայություններ, ինչպես նաև ապրանքներ կամ ծառայություններ, որոնք չունեն սպառողական արժեք:</li>
|
||||
<li>6.4.41. Տրանսցենդենտ ծառայություններ և ոչ ավանդական բժշկության ծառայություններ:</li>
|
||||
<li>6.4.42. Ծառայություններ` լիցենզավորված ծրագրային ապահովման փոխարինման կամ իրավատիրոջ կողմից տեղադրված տեխնիկական պաշտպանության միջոցների աշխատանքի խափանման համար հեռախոսներում, սմարթֆոններում, նոթբուքերում, նավիգատորներում, անհատական համակարգիչներում և այլն:</li>
|
||||
<li>6.4.43. Այլ ապրանքներ կամ ծառայություններ, որոնց շրջանառությունն արգելված է կամ սահմանափակված է Ռուսաստանի Դաշնության օրենսդրությամբ, ինչպես նաև կարող է բացասաբար ազդել միջազգային վճարային համակարգերի գործարար համբավի վրա:</li>
|
||||
<li>6.4.44. Ներարկային դեղամիջոցներ և լուծույթներ, ինչպես նաև դրանց արտադրության համար կիրառվող նյութեր:</li>
|
||||
<li>6.4.45. Ծառայություններ, աշխատանքներ և նյութեր, որոնք կապված են օկուլտ կազմակերպությունների և աղանդների գործունեության իրականացման հետ:</li>
|
||||
<li>6.4.46. Ֆինանսական բուրգերի ձևաչափով կազմակերպված ընկերությունների կողմից իրացվող ապրանքներ և ծառայություններ:</li>
|
||||
<li>6.4.47. Հնաոճ իրեր:</li>
|
||||
<li>6.4.48. Կենսաբանորեն ակտիվ հավելումներ: Սննդային ԲԱՀ-երի վաճառքը հնարավոր է միայն դեղատների, դեղատնային խանութների, դեղատնային կրպակների, դիետիկ ապրանքների մասնագիտացված խանութների, ինչպես նաև հատուկ բաժիններ և սեկցիաներ ունեցող մթերային խանութների միջոցով:</li>
|
||||
<li>6.4.49. Պատվերով կուրսային աշխատանքներ և դիպլոմներ:</li>
|
||||
<li>6.4.50. Անանուն աշխատանք (թաքստոցներով զբաղվողներ և այլն):</li>
|
||||
<li>6.4.51. Բնօրինակ ապրանքների պատճեններ և կրկնօրինակներ:</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section class="legal-section">
|
||||
<h2>7. Կայքի բովանդակության բացառիկ իրավունքներ</h2>
|
||||
|
||||
<p><strong>7.1. Մտավոր սեփականության օբյեկտներ</strong></p>
|
||||
<p>Կայքում հասանելի ողջ բովանդակությունը, ներառյալ.</p>
|
||||
<ul>
|
||||
<li>դիզայնի տարրեր,</li>
|
||||
<li>տեքստային նյութեր,</li>
|
||||
<li>գրաֆիկա և պատկերներ,</li>
|
||||
<li>տեսանյութեր,</li>
|
||||
<li>համակարգչային ծրագրեր,</li>
|
||||
<li>տվյալների բազաներ,</li>
|
||||
<li>այլ նյութեր -</li>
|
||||
</ul>
|
||||
<p>հանդիսանում է Կայքի սեփականատիրոջ և այլ իրավատերերի բացառիկ հեղինակային իրավունքների օբյեկտ:</p>
|
||||
|
||||
<p><strong>7.2. Բովանդակության օգտագործում</strong></p>
|
||||
<p>Բովանդակության օգտագործումը թույլատրվում է միայն կայքի ֆունկցիոնալ հնարավորությունների սահմաններում: Կայքի տարրերի կամ տեղադրված բովանդակության ցանկացած այլ օգտագործում առանց սեփականատերերի նախնական թույլտվության անթույլատրելի է:</p>
|
||||
|
||||
<p><strong>7.3. Անձնական օգտագործում</strong></p>
|
||||
<p>Օգտատերն իրավունք ունի օգտագործել կայքի բովանդակությունը անձնական ոչ առևտրային նպատակներով, պայմանով, որ պահպանվում են հեղինակային իրավունքի, հարակից իրավունքների, ապրանքային նշանների և հեղինակության մասին այլ նշումները:</p>
|
||||
</section>
|
||||
|
||||
<section class="legal-section">
|
||||
<h2>8. Երրորդ անձանց կայքեր և բովանդակություն</h2>
|
||||
|
||||
<p><strong>8.1. Արտաքին ռեսուրսների հղումների առկայություն</strong></p>
|
||||
<p>Կայքը կարող է ներառել հիպերհղումներ դեպի ինտերնետում գտնվող երրորդ անձանց ռեսուրսներ: Այդ ռեսուրսները Կայքի սեփականատիրոջ կողմից չեն ստուգվում օրենսդրական նորմերին կամ այլ չափանիշներին համապատասխանության տեսանկյունից: Համապատասխանաբար, երրորդ անձանց կայքերում առկա բովանդակության և նյութերի համար պատասխանատվությունը չի մտնում Կայքի սեփականատիրոջ իրավասության մեջ:</p>
|
||||
|
||||
<p><strong>8.2. Հղումների բնույթը</strong></p>
|
||||
<p>Երրորդ կողմի կայքերի հղումները, ինչպես նաև կայքում առկա ապրանքների, ծառայությունների կամ այլ առևտրային կամ ոչ առևտրային տեղեկատվության հիշատակումները չեն նշանակում Կայքի սեփականատիրոջ կողմից դրանց հավանություն կամ առաջարկություն:</p>
|
||||
|
||||
<p><strong>8.3. Մեջբերման պահանջներ</strong></p>
|
||||
<p>Կայքի նյութերի ցանկացած վերարտադրության դեպքում անհրաժեշտ է նշել ակտիվ հղում դեպի աղբյուրը:</p>
|
||||
|
||||
<p><strong>8.4. Մտավոր սեփականություն</strong></p>
|
||||
<p>Լոգոն, ֆիրմային անվանումը, տեսողական ձևավորումը և կայքի ընդհանուր տեսքը պատկանում են Կայքի սեփականատիրոջ մտավոր իրավունքներին: Դրանց օգտագործումը առանց Կայքի սեփականատիրոջ ուղղակի և հստակ թույլտվության արգելվում է:</p>
|
||||
</section>
|
||||
|
||||
<section class="legal-section">
|
||||
<h2>9. Կողմերի պատասխանատվությունը</h2>
|
||||
|
||||
<p><strong>9.1. Ընդհանուր պատասխանատվություն</strong></p>
|
||||
<p>Կայքը տեղեկատվական-տեխնոլոգիական ռեսուրս է, որն ապահովում է ապրանքների և ծառայությունների մասին տեղեկատվության տեղադրումը, ինչպես նաև գործարքների կատարման անվտանգությունը: Կայքի սեփականատերը պատասխանատվություն է կրում ռեսուրսում արգելված ապրանքների տեղակայման կանխարգելման, ինչպես նաև հարթակում ներկայացված ապրանքների և ծառայությունների մասին տեղեկատվության որակի և արժանահավատության համար:</p>
|
||||
|
||||
<p><strong>9.2. Պատասխանատվության սահմանափակումներ</strong></p>
|
||||
<p>Կայքի սեփականատերը չի երաշխավորում.</p>
|
||||
<ul>
|
||||
<li>Կայքի համապատասխանությունը օգտատիրոջ պահանջներին:</li>
|
||||
<li>Սերվիսի մշտական հասանելիությունը, արագությունը և սխալների բացակայությունը:</li>
|
||||
</ul>
|
||||
|
||||
<p><strong>9.3. Տեղեկատվության օգտագործման հետևանքներ</strong></p>
|
||||
<p>Կայքի միջոցով ստացվող ողջ տեղեկատվությունն ու նյութերը օգտատերն օգտագործում է իր հայեցողությամբ և ռիսկով: Օգտատերը պատասխանատվություն է կրում այդ տեղեկությունների օգտագործման հնարավոր բացասական հետևանքների համար:</p>
|
||||
|
||||
<p><strong>9.4. Մասնակիցների նույնականացում և Վաճառողների վերահսկում</strong></p>
|
||||
<p>Գնորդը նույնականացվում է հեռախոսահամարի և Telegram-ի միջոցով տրամադրված տվյալների հիման վրա: Յուրաքանչյուր Վաճառող անցնում է ամբողջական նույնականացման (ոնբորդինգ) գործընթաց, և նրա տվյալները հասանելի են Կայքի սեփականատիրոջը` վեճերի դեպքում օգտագործելու համար: Կայքի սեփականատերը իրականացնում է Վաճառողների գործունեության ստուգում և վերահսկում հարթակում:</p>
|
||||
|
||||
<p><strong>9.5. Հաշվի անվտանգություն</strong></p>
|
||||
<p>Օգտատերը ինքնուրույն պատասխանատու է իր պրոֆիլ մուտք գործելու միջոցների գաղտնիության պահպանման համար:</p>
|
||||
|
||||
<p><strong>9.6. Վաճառողի պատասխանատվություն</strong></p>
|
||||
<p>Վաճառողը լիովին պատասխանատու է վաճառվող արտադրանքի որակի, անվտանգության և հայտարարված բնութագրերին համապատասխանության, ինչպես նաև Գնորդի նկատմամբ պարտավորությունների խախտման հետևանքով առաջացած վնասների համար:</p>
|
||||
|
||||
<p><strong>9.7. Կայքի սեփականատիրոջ պատասխանատվությունը և պահանջների կարգավորման ընթացակարգը</strong></p>
|
||||
<p>Կայքի սեփականատերը պատասխանատու է հարթակում տեղադրված ապրանքների և ծառայությունների մասին տեղեկատվության որակի, անվտանգության և արժանահավատության համար: Միևնույն ժամանակ Կայքի սեփականատերը պատասխանատվություն չի կրում հետևյալի համար.</p>
|
||||
<ul>
|
||||
<li>Վաճառողների կողմից Գնորդների հանդեպ իրենց պարտավորությունների կատարումը կամ ոչ պատշաճ կատարումը:</li>
|
||||
<li>Երրորդ անձանց իրավունքների, ներառյալ մտավոր սեփականության, խախտումը:</li>
|
||||
<li>Առաքման, կոմպլեկտացիայի և ապրանքների վիճակի հետ կապված հարցերը:</li>
|
||||
</ul>
|
||||
<p>Գնորդը համաձայնում է, որ ապրանքների որակի, քանակի, կոմպլեկտացիայի և ծառայությունների վերաբերյալ պահանջները կարող են ուղղվել ինչպես Վաճառողին, այնպես էլ կայքի Ադմինիստրացիային: Կայքի Ադմինիստրացիան պատասխանատվություն է ստանձնում հարթակի միջոցով տրամադրվող ծառայությունների որակի և արժանահավատության համար և ակտիվորեն մասնակցում է վիճահարույց իրավիճակների կարգավորմանը:</p>
|
||||
|
||||
<p><strong>9.8. Առաքման պատասխանատվություն</strong></p>
|
||||
<p>Ապրանքների առաքման ժամկետների, պայմանների և որակի համար պատասխանատվությունը կրում են տրանսպորտային ընկերություններն ու սուրհանդակային ծառայությունները: Կայքի սեփականատերը հանդես է գալիս միայն որպես տեղեկատվական միջնորդ և պատասխանատվություն չի կրում առաքման ծառայությունների գործողությունների համար:</p>
|
||||
|
||||
<p><strong>9.9. Օգտատիրոջ պատասխանատվությունը երրորդ անձանց առջև</strong></p>
|
||||
<p>Օգտատերը անձամբ պատասխանատու է երրորդ անձանց առջև կայքի օգտագործման հետ կապված իր գործողությունների համար:</p>
|
||||
|
||||
<p><strong>9.10. Ֆորս-մաժորային հանգամանքներ</strong></p>
|
||||
<p>Կայքի աշխատանքը կարող է կասեցվել չնախատեսված հանգամանքների, վթարների, սարքավորումների խափանումների կամ երրորդ անձանց միջամտության դեպքում` առանց նախնական ծանուցումների:</p>
|
||||
|
||||
<p><strong>9.11. Գովազդի պատասխանատվություն</strong></p>
|
||||
<p>Գովազդային հայտարարությունների բովանդակության համար պատասխանատվությունը կրում են Վաճառողները, որոնք տեղադրում են իրենց ապրանքների և ծառայությունների մասին տեղեկատվությունը: Կայքի սեփականատերը տրամադրում է միայն տեղեկատվության տեղադրման տեխնիկական հարթակը:</p>
|
||||
|
||||
<p><strong>9.12. Բնական աղետներ և արտակարգ իրադարձություններ</strong></p>
|
||||
<p>Ոչ մի կողմ պատասխանատվություն չի կրում պարտավորությունների չկատարման համար, եթե դա պայմանավորված է անհաղթահարելի ուժի հանգամանքներով, ինչպիսիք են բնական աղետները, պատերազմները կամ տեխնածին վթարները:</p>
|
||||
</section>
|
||||
|
||||
<section class="legal-section">
|
||||
<h2>10. Ապրանքը և գնման կատարման կարգը</h2>
|
||||
|
||||
<p><strong>10.1. Պատվերի ձևակերպում</strong></p>
|
||||
<p>Պատվերը ձևակերպվում է Գնորդի կողմից` խստորեն համաձայն կայքում սահմանված ընթացակարգի:</p>
|
||||
|
||||
<p><strong>10.2. Սխալ տվյալների համար պատասխանատվություն</strong></p>
|
||||
<p>Գնորդը ստանձնում է պատվերը չստանալու ռիսկերը, որոնք կապված են ձևակերպման ժամանակ տրամադրված սխալ կամ ոչ ամբողջական տեղեկատվության հետ:</p>
|
||||
|
||||
<p><strong>10.3. Առաքման վերաբերյալ նախնական տեղեկատվություն</strong></p>
|
||||
<p>Պատվերի ձևավորումից հետո Գնորդը ստանում է ծանուցում առաքման մոտավոր ամսաթվի մասին` գրանցման ժամանակ նշված էլեկտրոնային փոստի կամ հեռախոսի միջոցով:</p>
|
||||
|
||||
<p><strong>10.4. Առաքման ժամանակի հստակեցում</strong></p>
|
||||
<p>Առաքումից առաջ խանութի աշխատակիցը կապ կհաստատի Գնորդի հետ հեռախոսով` առաքման ճշգրիտ ժամանակը հստակեցնելու համար:</p>
|
||||
|
||||
<p><strong>10.5. Առաքման ակնկալվող ժամանակի ճշգրտում</strong></p>
|
||||
<p>Պատվերի մենեջերը տեղեկացնում է Գնորդին պատվերը առաքման ծառայությանը փոխանցելու նախատեսվող ամսաթվի մասին` էլեկտրոնային փոստով կամ զանգով:</p>
|
||||
|
||||
<p><strong>10.6. Ապրանքի պակասի հնարավորությունը</strong></p>
|
||||
<p>Վաճառողը չի երաշխավորում պատվիրված ապրանքի մշտական առկայությունը պահեստում պատվերի մշակման պահին:</p>
|
||||
|
||||
<p><strong>10.11. Մատակարարման օրենսդրական շրջանակ</strong></p>
|
||||
<p>Ապրանքների մատակարարումը իրականացվում է Ռուսաստանի Դաշնության և Վաճառողի ծագման երկրի օրենքներին համապատասխան:</p>
|
||||
|
||||
<p><strong>10.12. Ռուսաստանի օրենսդրության կիրառելիություն</strong></p>
|
||||
<p>Ֆիզիկական ապրանքները փոխանցվում են գնորդին Ռուսաստանի Դաշնության օրենսդրությանը համապատասխան:</p>
|
||||
</section>
|
||||
|
||||
<section class="legal-section">
|
||||
<h2>11. Պատվերի առաքում</h2>
|
||||
|
||||
<p><strong>11.1. Առաքման եղանակներ և ժամկետներ</strong></p>
|
||||
<p>Ապրանքների առաքման եղանակներն ու մոտավոր ժամկետները նշված են կայքում: Փաստացի ժամկետները կարող են ճշգրտվել պատվերը հաստատելիս call-center-ի աշխատակցի կամ Վաճառողի ներկայացուցչի կողմից:</p>
|
||||
|
||||
<p><strong>11.2. Թվային ապրանքների մատակարարման հաստատում</strong></p>
|
||||
<p>Թվային ապրանքների մատակարարման փաստը հաստատվում է գրանցման ժամանակ նշված հասցեին թվային ֆայլի կամ կոդի կցմամբ էլեկտրոնային նամակ ուղարկելով: Նման նամակի ստացումը նշանակում է, որ թվային ապրանքի մատակարարման ծառայությունը կատարվել է:</p>
|
||||
<p>Ֆիզիկական ապրանքը համարվում է առաքված այն պահին, երբ այն փաստացի հանձնվում է Գնորդին կամ նրա կողմից նշանակված ստացողին` ընտրված առաքման պայմաններին համապատասխան:</p>
|
||||
|
||||
<p><strong>11.3. Առաքման տարածք</strong></p>
|
||||
<p>Վաճառողի կողմից առաջարկվող ապրանքների առաքման տարածքային սահմանները հրապարակվում են կայքում:</p>
|
||||
|
||||
<p><strong>11.4. Ապրանքի ընդունում</strong></p>
|
||||
<p>Առաքման ժամանակ ապրանքը հանձնվում է Գնորդին կամ պատվերում նշված երրորդ անձին:</p>
|
||||
|
||||
<p><strong>11.5. Անձի ստուգում</strong></p>
|
||||
<p>Նախապես վճարված պատվերը հանձնելիս առաքման ծառայությունը կարող է խնդրել ներկայացնել անձը հաստատող փաստաթուղթ` խարդախության ռիսկը բացառելու համար:</p>
|
||||
|
||||
<p><strong>11.6. Ապրանքի պատահական կորստի ռիսկի անցում</strong></p>
|
||||
<p>Ապրանքի պատահական կորստի կամ վնասման ռիսկը անցնում է Գնորդին պատվերի անմիջական հանձնման պահին:</p>
|
||||
|
||||
<p><strong>11.7. Առաքման արժեքի հաշվարկ</strong></p>
|
||||
<p>Առաքման արժեքը հաշվարկվում է անհատապես յուրաքանչյուր պատվերի համար` հաշվի առնելով քաշը, տարածաշրջանը և ընտրված փոխադրման եղանակը:</p>
|
||||
|
||||
<p><strong>11.8. Վաճառողի պարտավորությունների ավարտ</strong></p>
|
||||
<p>Վաճառողը համարվում է կատարել իր պարտավորությունները ապրանքը հանձնելու մասով, եթե ապրանքը հանձնվել է Գնորդին սուրհանդակի միջոցով կամ տրամադրվել է Գնորդին փոստային բաժանմունքում կամ այլ համաձայնեցված վայրում:</p>
|
||||
|
||||
<p><strong>11.9. Ապրանքի զննում ստանալիս</strong></p>
|
||||
<p>Ապրանքը ստանալիս Գնորդն իրավունք ունի տեսողականորեն գնահատել դրա վիճակը և անհրաժեշտության դեպքում զննել այն Վաճառողի աշխատակցի կամ սուրհանդակի ներկայությամբ:</p>
|
||||
|
||||
<p><strong>11.10. Ապրանքի ստուգում սուրհանդակից ընդունելիս</strong></p>
|
||||
<p>Գնորդը կարող է զննել ստացված ապրանքը և համոզվել դրա համապատասխանության մեջ հայտարարված քանակին, տեսականուն և կոմպլեկտացիային:</p>
|
||||
|
||||
<p><strong>11.11. Սուրհանդակային առաքման ժամանակային սահմանափակումներ</strong></p>
|
||||
<p>Սուրհանդակները Գնորդի հասցեում կարող են գտնվել սահմանափակ ժամանակ` առավելագույնը 20 րոպե:</p>
|
||||
|
||||
<p><strong>11.12. Ապրանքի սերտիֆիկացում</strong></p>
|
||||
<p>Կայքում տեղադրված ապրանքները համապատասխանում են պետական ստանդարտներին (ԳՕՍՏ) և տեխնիկական պայմաններին (ՏՊ), ինչը հաստատվում է հավաստագրերով և այլ անհրաժեշտ փաստաթղթերով:</p>
|
||||
</section>
|
||||
|
||||
<section class="legal-section">
|
||||
<h2>12. Ապրանքի վճարում</h2>
|
||||
|
||||
<p><strong>12.1. Արժույթ և գնի կառուցվածք</strong></p>
|
||||
<p>Կայքում տեղադրված ապրանքների գինը արտահայտվում է Ռուսաստանի Դաշնության ռուբլիներով և ներառում է բոլոր հարկային վճարումները և պարտադիր գանձումները:</p>
|
||||
|
||||
<p><strong>12.2. Գների հնարավոր սխալներ</strong></p>
|
||||
<p>Երբեմն կայքում կարող են առաջանալ տեխնիկական սխալներ, որոնք հանգեցնում են ապրանքների կամ առաքման արժեքի սխալ արտացոլման: Նման սխալների հայտնաբերման դեպքում Վաճառողը տեղեկացնում է Գնորդին և ճշգրտում է գինը` թողնելով Գնորդին պատվերը թարմացված պայմաններով հաստատելու կամ գործարքը չեղարկելու ընտրություն:</p>
|
||||
|
||||
<p><strong>12.3. Գների փոփոխություն</strong></p>
|
||||
<p>Վաճառողն իրավունք ունի միակողմանի կարգով փոխել ապրանքների գները: Սակայն եթե ապրանքի համար արդեն վճարվել է, տվյալ ապրանքի գնի փոփոխություն չի թույլատրվում:</p>
|
||||
|
||||
<p><strong>12.4. Վճարման եղանակներ</strong></p>
|
||||
<p>Գնորդին հասանելի վճարման տարբերակները ներկայացված են կայքում պատվերի ձևակերպման ընթացքում: Վճարման եղանակն ընդունվում է Օգտատիրոջ ընտրության հիման վրա հասանելի տարբերակներից:</p>
|
||||
|
||||
<p><strong>12.6. Բանկային քարտերով վճարման առանձնահատկություններ</strong></p>
|
||||
<p>Բանկային քարտերով վճարելիս գործում են հետևյալ կանոնները.</p>
|
||||
<ul>
|
||||
<li>Վճարումները կատարվում են քարտատիրոջ կամ լիազորված անձի կողմից:</li>
|
||||
<li>Գործարքների հեղինակացումը կատարվում է բանկային կազմակերպության միջոցով:</li>
|
||||
<li>Վաճառողն իրավունք ունի պահանջել անձը հաստատող փաստաթուղթ` քարտից օգտվելու լիազորությունը հաստատելու համար:</li>
|
||||
<li>Կայքում բանկային քարտով վճարում կատարելիս Գնորդը համաձայնում է էլեկտրոնային փոստով էլեկտրոնային դրամարկղային կտրոն ստանալուն:</li>
|
||||
<li>Քարտով վճարված պատվերները ստուգվում են Վաճառողի կողմից` խարդախությունը կանխելու նպատակով:</li>
|
||||
<li>Գնորդների բանկային քարտերի տվյալների հավաքագրում և պահպանում չի իրականացվում ոչ Կայքի սեփականատիրոջ, ոչ էլ Վաճառողի կողմից:</li>
|
||||
</ul>
|
||||
|
||||
<p><strong>12.7. Զեղչեր և բոնուսներ</strong></p>
|
||||
<p>Վաճառողն իրավունք ունի սահմանել զեղչեր և ներդնել բոնուսային ծրագրեր: Զեղչերի տեսակները, տրամադրման կարգը և պայմանները սահմանվում են Վաճառողի կողմից և հրապարակվում են կայքում:</p>
|
||||
|
||||
<p><strong>12.13. Կանխիկ վճարման գումարի սահմանափակումներ</strong></p>
|
||||
<p>Ապրանքի վճարումը կանխիկ եղանակով չի իրականացվում:</p>
|
||||
|
||||
<p><strong>12.14. Դրամական միջոցների վերադարձի ժամկետներ</strong></p>
|
||||
<p>Ապրանքի համար դրամական միջոցների վերադարձի մասին Գնորդի պահանջները բավարարվում են համապատասխան դիմումը ներկայացնելու պահից 10 օրվա ընթացքում:</p>
|
||||
</section>
|
||||
|
||||
<section class="legal-section">
|
||||
<h2>13. Ապրանքի վերադարձ և փոխանակում</h2>
|
||||
|
||||
<p><strong>13.1. Վերադարձի ընդհանուր կանոններ</strong></p>
|
||||
<p>Թվային ապրանքները (էլեկտրոնային ձևով տրամադրվող) վերադարձման ենթակա չեն` ռուսական օրենսդրությանը համապատասխան: Ֆիզիկական ապրանքների վերադարձը կատարվում է <a [routerLink]="'/return-policy' | langRoute">«Վերադարձի քաղաքականություն»</a> բաժնի և սպառողների իրավունքների մասին գործող օրենքների համաձայն:</p>
|
||||
|
||||
<p><strong>13.2. Ապրանքի վերադարձ</strong></p>
|
||||
<p>Կայքում ներկայացված և վերադարձման ենթակա ապրանքների վերադարձը կամ փոխարինումը կատարվում է սույն համաձայնագրին և Ռուսաստանի Դաշնության օրենսդրությանը համապատասխան:</p>
|
||||
|
||||
<p><strong>13.4. Ակցիոն հավաքածուներ</strong></p>
|
||||
<p>Եթե ապրանքների հավաքածուն ձեռք է բերվել ակցիայով և զեղչով, վերադարձը կամ փոխանակումը հնարավոր է միայն ամբողջ հավաքածուի համար: Հավաքածուից առանձին ապրանքներ վերադարձնել հնարավոր չէ:</p>
|
||||
|
||||
<p><strong>13.5. Առաքման ծախսերի փոխհատուցում</strong></p>
|
||||
<p>Որակյալ ապրանքը վերադարձնելու դեպքում Վաճառողը կամ Կայքի սեփականատերը իրավունք ունի Գնորդից գանձել ապրանքի առաքման ծախսերը:</p>
|
||||
|
||||
<p><strong>13.6. Պահանջների բավարարման ժամկետներ</strong></p>
|
||||
<p>Դրամական միջոցների վերադարձի դիմումները բավարարվում են ներկայացման պահից 10 օրվա ընթացքում:</p>
|
||||
|
||||
<p><strong>13.6.7. Փաստաթղթեր ապրանքի վերադարձի դեպքում</strong></p>
|
||||
<p>Ապրանքը վերադարձնելիս Գնորդը պարտավոր է տրամադրել հետևյալ փաստաթղթերը.</p>
|
||||
<ul>
|
||||
<li>Վերադարձի դիմում:</li>
|
||||
<li>Վճարման անդորրագրի կամ կտրոնի պատճեն:</li>
|
||||
<li>Ընդունման-հանձնման ակտի (կամ ներդրվածքի ցանկի) պատճեն:</li>
|
||||
</ul>
|
||||
|
||||
<p><strong>13.6.9. Դրամական միջոցների վերադարձի մեխանիզմ</strong></p>
|
||||
<p>Դրամական միջոցների վերադարձն իրականացվում է վճարված ապրանքի արժեքը վերադարձնելու միջոցով: Վերադարձի եղանակը նշվում է վերադարձի դիմումում:</p>
|
||||
</section>
|
||||
|
||||
<section class="legal-section">
|
||||
<h2>14. Համաձայնագրի գործողության ժամկետը</h2>
|
||||
|
||||
<p><strong>14.1. Գործողության սկիզբ և դադարեցում</strong></p>
|
||||
<p>Համաձայնագիրն ուժի մեջ է մտնում Օգտատիրոջ կամ Գնորդի կողմից այն ընդունելու (ակցեպտելու) պահից և գործում է մինչև հանրային օֆերտայի ակցեպտը հետ կանչելու պահը: Օֆերտայի հետկանչը ենթադրում է համաձայնագրի գործողության անհապաղ դադարեցում:</p>
|
||||
|
||||
<p><strong>14.2. Օֆերտան հետ կանչելու իրավունք</strong></p>
|
||||
<p>Կայքի սեփականատերն իրավունք ունի հետ կանչել սույն առաջարկը` Ռուսաստանի Դաշնության քաղաքացիական օրենսգրքի 436-րդ հոդվածով նախատեսված կարգով:</p>
|
||||
</section>
|
||||
|
||||
<section class="legal-section">
|
||||
<h2>15. Վեճերի լուծման և պահանջների կարգավորման կարգը</h2>
|
||||
|
||||
<p><strong>15.1. Վեճերի կամավոր կարգավորում</strong></p>
|
||||
<p>Եթե Օգտատիրոջ և Կայքի սեփականատիրոջ միջև առաջանում են տարաձայնություններ, որոնք կապված են համաձայնագրի պայմանների կատարման հետ, երկու կողմերն էլ պարտավոր են փորձել լուծել խնդիրը փոխադարձ խորհրդակցությունների և բանակցությունների միջոցով: Սահմանվում է պարտադիր նախադատական կարգ:</p>
|
||||
|
||||
<p><strong>15.2. Պահանջ ներկայացնելու կարգ</strong></p>
|
||||
<p>Պահանջների քննության ընթացակարգը նախատեսում է հետևյալ փուլերը.</p>
|
||||
<ul>
|
||||
<li>Օգտատերը, որը կարծում է, որ իր իրավունքները խախտվել են Կայքի սեփականատիրոջ գործողությամբ կամ անգործությամբ, ուղարկում է համապատասխան պահանջ` նշելով պահանջի էությունը:</li>
|
||||
<li>Պահանջը ստանալուց հետո 25 աշխատանքային օրվա ընթացքում Կայքի սեփականատերը պարտավոր է պատասխան պատրաստել և ներկայացնել իր դիրքորոշումը:</li>
|
||||
<li>Եթե փոխզիջման հասնել չի հաջողվում, վեճը քննվում է դատական կարգով` համաձայն համաձայնագրի 15.5 կետի:</li>
|
||||
</ul>
|
||||
|
||||
<p><strong>15.3. Պահանջների քննություն</strong></p>
|
||||
<p>Կայքի սեփականատերը չի ընդունում անանուն պահանջներ կամ բողոքներ, որոնք բավարար տեղեկություն չեն պարունակում դիմողի նույնականացման համար:</p>
|
||||
|
||||
<p><strong>15.5. Վեճերի դատական քննություն</strong></p>
|
||||
<p>Եթե բանակցությունները և պահանջների նախադատական կարգավորումը չեն հանգեցնում համաձայնության, վեճը լուծվում է դատական կարգով` Կայքի սեփականատիրոջ գտնվելու վայրով:</p>
|
||||
</section>
|
||||
|
||||
<section class="legal-section">
|
||||
<h2>16. Այլ պայմաններ</h2>
|
||||
|
||||
<p><strong>16.1. Համաձայնագրի գործողությունը</strong></p>
|
||||
<p>Սույն փաստաթուղթը հանդիսանում է Օգտատիրոջ և Կայքի սեփականատիրոջ միջև ռեսուրսի օգտագործման վերաբերյալ պաշտոնական համաձայնագիր և փոխարինում է բոլոր նախորդ պայմանավորվածությունները:</p>
|
||||
|
||||
<p><strong>16.2. Համաձայնություն պայմաններին</strong></p>
|
||||
<p>Օգտատերը, շարունակելով օգտագործել կայքը, արտահայտում է իր համաձայնությունը համաձայնագրի պայմաններին: Անհամաձայնությունը ենթադրում է անձնական հաշվի հեռացում:</p>
|
||||
|
||||
<p><strong>16.3. Կիրառվող օրենսդրություն</strong></p>
|
||||
<p>Համաձայնագրով չկարգավորված հարցերը լուծվում են Հայաստանի օրենսդրությանը համապատասխան:</p>
|
||||
|
||||
<p><strong>16.4. «Օրենսդրություն» տերմինի սահմանում</strong></p>
|
||||
<p>Համաձայնագրի ողջ տեքստում «օրենսդրություն» տերմինը, եթե հատուկ այլ բան նշված չէ, ենթադրում է Հայաստանի օրենքները:</p>
|
||||
|
||||
<p><strong>16.5. Անվճար ծառայություններ</strong></p>
|
||||
<p>Համաձայնագրի շրջանակում տրամադրվող անվճար ծառայությունները չեն ենթադրում սպառողների իրավունքների պաշտպանության մասին օրենսդրության նորմերի կիրառում Օգտատիրոջ և Վաճառողի հարաբերությունների նկատմամբ:</p>
|
||||
|
||||
<p><strong>16.6. Բացակայող հարաբերություններ</strong></p>
|
||||
<p>Համաձայնագրի ոչ մի դրույթ չի կարող մեկնաբանվել որպես գործակալական հարաբերությունների, գործընկերության, համատեղ ձեռնարկության, աշխատանքային հարաբերությունների կամ այլ հարաբերությունների հաստատում, որոնք ուղղակիորեն նախատեսված չեն համաձայնագրով:</p>
|
||||
|
||||
<p><strong>16.7. Կետերի անվավեր ճանաչում</strong></p>
|
||||
<p>Համաձայնագրի մեկ կամ մի քանի դրույթների անվավեր ճանաչումը չի ազդում մնացած կետերի իրավաբանական ուժի և կիրառելիության վրա:</p>
|
||||
|
||||
<p><strong>16.8. Արձագանք խախտումներին</strong></p>
|
||||
<p>Օգտատերերի կողմից համաձայնագրերի խախտման դեպքում Կայքի սեփականատիրոջ չմիջամտելը հետագայում չի խոչընդոտում նրա շահերի պաշտպանության միջոցների կիրառմանը:</p>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
import { Component, ChangeDetectionStrategy } from '@angular/core';
|
||||
import { RouterLink } from "@angular/router";
|
||||
import { LangRoutePipe } from '../../../../pipes/lang-route.pipe';
|
||||
|
||||
@Component({
|
||||
selector: 'app-public-offer-hy',
|
||||
templateUrl: './public-offer-hy.component.html',
|
||||
styleUrls: ['../public-offer.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
imports: [RouterLink, LangRoutePipe]
|
||||
})
|
||||
export class PublicOfferHyComponent {}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { Component, ChangeDetectionStrategy, inject } from '@angular/core';
|
||||
import { LanguageService } from '../../../services/language.service';
|
||||
import { PublicOfferRuComponent } from './ru/public-offer-ru.component';
|
||||
import { PublicOfferEnComponent } from './en/public-offer-en.component';
|
||||
import { PublicOfferHyComponent } from './hy/public-offer-hy.component';
|
||||
import { PublicOfferRuComponent } from './ru/public-offer-ru.component';
|
||||
|
||||
@Component({
|
||||
selector: 'app-public-offer',
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
|
||||
<li><strong>Покупатель</strong> — зарегистрированный Пользователь, который сделал заказ через сайт.</li>
|
||||
|
||||
<li><strong>Администратор или Владелец Сайта</strong> — юридическое лицо ООО "ИНТ ФИН ЛОГИСТИК", идентификационный налоговый номер (ИНН) 9909697628.</li>
|
||||
<li><strong>Администратор или Владелец Сайта</strong> — юридические лица ООО "ИНТ ФИН ЛОГИСТИК" (ИНН 9909697628) и ООО "ИНТ ФАКТОРИНГ" (ИНН 9909697635).</li>
|
||||
|
||||
<li><strong>Продавец или Селлер</strong> — физические или юридические лица, предприниматели, предлагающие товары и услуги на ресурсе. Продавцы несут личную ответственность за качество, безопасность и соответствие описания товаров.</li>
|
||||
|
||||
@@ -177,6 +177,62 @@
|
||||
|
||||
<p><strong>6.3. Права Пользователя</strong></p>
|
||||
<p>Пользователь имеет право отказаться от получения рекламных сообщений, воспользовавшись соответствующим инструментом на сайте или направив заявку по электронной почте <a href="mailto:info@dexarmarket.ru">info@dexarmarket.ru</a> или письмом по официальному адресу Владельца сайта.</p>
|
||||
|
||||
<p><strong>6.4. Запрещённые товары для продажи на сайте</strong></p>
|
||||
<p>На сайте запрещается размещение и продажа следующих категорий товаров и услуг:</p>
|
||||
<ul>
|
||||
<li>6.4.1. Вооружение, боеприпасы к нему, военная техника, запасные части, комплектующие изделия и приборы к ним, взрывчатые вещества, средства взрывания, все виды ракетного топлива, а также специальные материалы и специальное оборудование для их производства, специальное снаряжение военизированных организаций и нормативно-техническая продукция на их производство и эксплуатацию.</li>
|
||||
<li>6.4.2. Ракетно-космические комплексы, системы связи и управления военного назначения и нормативно-техническая документация на их производство и эксплуатацию.</li>
|
||||
<li>6.4.3. Боевые отравляющие вещества, средства защиты от них и нормативно-техническая документация на их производство и использование.</li>
|
||||
<li>6.4.4. Результаты научно-исследовательских и проектных работ, а также фундаментальных поисковых исследований по созданию вооружения и военной техники.</li>
|
||||
<li>6.4.5. Услуги, работы и материалы, связанные с осуществлением военной службы и военизированной деятельности.</li>
|
||||
<li>6.4.6. Любое оружие, в том числе охотничье, гражданское и иное, а также комплектующие изделия к нему, ножи (за исключением кухонных, перочинных и канцелярских).</li>
|
||||
<li>6.4.7. Радиоактивные вещества и изотопы, уран и другие делящиеся материалы и изделия из них.</li>
|
||||
<li>6.4.8. Отходы радиоактивных материалов.</li>
|
||||
<li>6.4.9. Драгоценные и редкоземельные металлы, драгоценные камни, а также отходы, содержащие драгоценные и редкоземельные металлы и драгоценные камни.</li>
|
||||
<li>6.4.10. Рентгеновское оборудование, приборы и оборудование с использованием радиоактивных веществ и изотопов.</li>
|
||||
<li>6.4.11. Яды, наркотические средства и психотропные вещества, их прекурсоры.</li>
|
||||
<li>6.4.12. Спирт этиловый, алкогольные напитки.</li>
|
||||
<li>6.4.13. Лекарственные препараты, отпускаемые по рецепту, а также наркотические, психотропные и спиртосодержащие (с объёмной долей этилового спирта свыше 25%) лекарственные препараты и бальзамы на основе спирта.</li>
|
||||
<li>6.4.14. Лекарственное сырье, получаемое от северного оленеводства (панты и эндокринное сырье).</li>
|
||||
<li>6.4.15. Табачная продукция или продукты для вейпинга.</li>
|
||||
<li>6.4.16. Шифровальная техника и нормативно-техническая документация на ее производство и использование.</li>
|
||||
<li>6.4.17. Поддельные денежные знаки.</li>
|
||||
<li>6.4.18. Иностранная валюта и иные валютные ценности, монеты и банкноты Российской Федерации, находящиеся в обращении.</li>
|
||||
<li>6.4.19. Радиоэлектронные и специальные технические средства, предназначенные для негласного получения информации, а также высокочастотные устройства, состоящие из одного или нескольких радиопередающих устройств и (или) их комбинаций и вспомогательного оборудования, предназначенные для передачи и приема радиоволн на частоте выше 8 ГГц.</li>
|
||||
<li>6.4.20. Материалы и услуги, нарушающие тайну частной жизни, посягающие на честь, достоинство и деловую репутацию граждан и юридических лиц, а также содержащие государственную, банковскую, коммерческую и иную тайны.</li>
|
||||
<li>6.4.21. Государственные награды РФ, РСФСР, СССР, а также их копии.</li>
|
||||
<li>6.4.22. Государственные удостоверения личности, знаки, пропуска, разрешения, сертификаты, проездные документы и лицензии, а также иные документы, предоставляющие права или освобождающие от прав или обязанностей, бланки для этих документов, а также услуги по их получению.</li>
|
||||
<li>6.4.23. Объекты культурного наследия народов Российской Федерации, а также объекты археологического наследия.</li>
|
||||
<li>6.4.24. Человеческие органы и ткани, а также донорские услуги.</li>
|
||||
<li>6.4.25. Животные и растения, занесенные в Красную книгу Российской Федерации и Красные книги субъектов Российской Федерации, части и органы животных, занесенных в Красную книгу Российской Федерации и Красные книги субъектов Российской Федерации, а также животные и растения, охраняемые международными договорами Российской Федерации.</li>
|
||||
<li>6.4.26. Шкуры и изделия из шкур редких и находящихся под угрозой исчезновения видов животных в соответствии с действующим законодательством Российской Федерации.</li>
|
||||
<li>6.4.27. Рыболовные сети, материалы для их изготовления, а также услуги по их изготовлению, электроудочки и капканы, запрещенные к реализации на территории Российской Федерации.</li>
|
||||
<li>6.4.28. Экстремистские материалы, материалы, призывающие к массовым беспорядкам, осуществлению террористической и экстремистской деятельности, к участию в массовых публичных мероприятиях, разжиганию межнациональной и межконфессиональной розни.</li>
|
||||
<li>6.4.29. Предметы с нацистской символикой или символикой запрещенных в Российской Федерации организаций.</li>
|
||||
<li>6.4.30. Контрафактная или краденая продукция, или имущество.</li>
|
||||
<li>6.4.31. Базы данных, в том числе содержащие персональные данные, которые могут способствовать несанкционированным рассылкам.</li>
|
||||
<li>6.4.32. Материалы, передаваемые исключительно виртуально и не записанные на какой-либо материальный носитель (идеи, методы, принципы и т. д.).</li>
|
||||
<li>6.4.33. Игровое оборудование, используемое для проведения азартных игр, лотерейное оборудование, оказание услуг по приему ставок для участия в азартных играх в интернете, прием платежей за лотерейные билеты, квитанции и иные документы, удостоверяющие право на участие в лотерее, а также продажа виртуальной валюты.</li>
|
||||
<li>6.4.34. Документы на транспортные средства, государственные номера для транспортных средств.</li>
|
||||
<li>6.4.35. Товары, оборот которых нарушает интеллектуальные права третьих лиц (в том числе патенты, товарные знаки, авторские права и т. д.).</li>
|
||||
<li>6.4.36. Инвестиционные услуги, операции с денежными средствами и криптовалютами, а также товары и услуги, приобретение или использование которых гарантированно приносит заработок или прибыль.</li>
|
||||
<li>6.4.37. Товары и услуги, реализуемые организацией многоуровневого сетевого маркетинга, деятельность которых основана на создании сети независимых дистрибьюторов или сбытовых агентов.</li>
|
||||
<li>6.4.38. Услуги и (или) работа интимного, эротического или сексуального характера, а также порнографические или эротические материалы.</li>
|
||||
<li>6.4.39. Товары или услуги, использование которых может быть направлено на нарушение действующего законодательства Российской Федерации.</li>
|
||||
<li>6.4.40. Несуществующие товары или услуги, а также товары или услуги, не имеющие потребительской ценности.</li>
|
||||
<li>6.4.41. Трансцендентные услуги и услуги нетрадиционной медицины.</li>
|
||||
<li>6.4.42. Услуги по замене лицензионного программного обеспечения или нарушению работы установленных правообладателем средств технической защиты телефонов, смартфонов, ноутбуков, навигаторов, персональных компьютеров и т. д.</li>
|
||||
<li>6.4.43. Иные товары или услуги, оборот которых запрещен или ограничен согласно законодательству Российской Федерации, а также способен оказать негативное влияние на деловую репутацию международных платежных систем.</li>
|
||||
<li>6.4.44. Инъекционные препараты и растворы, а также вещества, применяемые для их изготовления.</li>
|
||||
<li>6.4.45. Услуги, работы и материалы, связанные с осуществлением деятельности оккультных организаций и сект.</li>
|
||||
<li>6.4.46. Товары и услуги, реализуемые компаниями по форме организации финансовых пирамид.</li>
|
||||
<li>6.4.47. Антиквариат.</li>
|
||||
<li>6.4.48. Биологически активные добавки. Продажа БАД к пище возможна только через аптечные учреждения (аптеки, аптечные магазины, аптечные киоски), специализированные магазины с диетическими продуктами, продовольственные магазины со специальными отделами и секциями.</li>
|
||||
<li>6.4.49. Курсовые и дипломы на заказ.</li>
|
||||
<li>6.4.50. Анонимная работа (закладчики и т. п.).</li>
|
||||
<li>6.4.51. Копии и реплики оригинальных товаров.</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section class="legal-section">
|
||||
|
||||
@@ -56,7 +56,7 @@
|
||||
@if (items().length > 0) {
|
||||
<div class="items-grid">
|
||||
@for (item of items(); track trackByItemId($index, item)) {
|
||||
<div class="item-card">
|
||||
<div class="item-card" (mouseenter)="onItemHover(item.itemID)">
|
||||
<a [routerLink]="['/item', item.itemID] | langRoute" class="item-link">
|
||||
<div class="item-image">
|
||||
<img [src]="getMainImage(item)" [alt]="itemName(item)" loading="lazy" decoding="async" width="300" height="300" />
|
||||
@@ -105,19 +105,29 @@
|
||||
</div>
|
||||
</a>
|
||||
|
||||
<button class="add-to-cart-btn" (click)="addToCart(item.itemID, $event)">
|
||||
<button class="add-to-cart-btn" (click)="addToCart(item.itemID, $event)" [attr.aria-label]="('search.addToCart' | translate) + ': ' + item.name">
|
||||
{{ 'search.addToCart' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
@if (loading() && items().length > 0) {
|
||||
<div class="loading-more">
|
||||
<div class="spinner"></div>
|
||||
<p>{{ 'search.loadingMore' | translate }}</p>
|
||||
</div>
|
||||
}
|
||||
@if (loading() && items().length > 0) {
|
||||
@for (i of skeletonSlots; track i) {
|
||||
<div class="item-card skeleton-card">
|
||||
<div class="item-link">
|
||||
<div class="item-image skeleton-image"></div>
|
||||
<div class="item-details">
|
||||
<div class="skeleton-line skeleton-title"></div>
|
||||
<div class="skeleton-line skeleton-rating"></div>
|
||||
<div class="skeleton-line skeleton-price"></div>
|
||||
<div class="skeleton-line skeleton-stock"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="skeleton-btn"></div>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
|
||||
@if (!hasMore() && items().length > 0) {
|
||||
<div class="no-more">
|
||||
|
||||
@@ -344,6 +344,59 @@
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
// Skeleton loading cards
|
||||
.skeleton-card {
|
||||
pointer-events: none;
|
||||
|
||||
.skeleton-image {
|
||||
background: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
|
||||
background-size: 200% 100%;
|
||||
animation: shimmer 1.5s infinite;
|
||||
}
|
||||
|
||||
.skeleton-line {
|
||||
border-radius: 6px;
|
||||
background: linear-gradient(90deg, #e8e8e8 25%, #d8d8d8 50%, #e8e8e8 75%);
|
||||
background-size: 200% 100%;
|
||||
animation: shimmer 1.5s infinite;
|
||||
}
|
||||
|
||||
.skeleton-title {
|
||||
height: 16px;
|
||||
width: 80%;
|
||||
}
|
||||
|
||||
.skeleton-rating {
|
||||
height: 12px;
|
||||
width: 50%;
|
||||
}
|
||||
|
||||
.skeleton-price {
|
||||
height: 18px;
|
||||
width: 40%;
|
||||
margin-top: auto;
|
||||
}
|
||||
|
||||
.skeleton-stock {
|
||||
height: 6px;
|
||||
width: 60px;
|
||||
}
|
||||
|
||||
.skeleton-btn {
|
||||
height: 42px;
|
||||
background: linear-gradient(90deg, #5a8a85 25%, #497671 50%, #5a8a85 75%);
|
||||
background-size: 200% 100%;
|
||||
animation: shimmer 1.5s infinite;
|
||||
border-radius: 0 0 13px 13px;
|
||||
margin-top: -1px;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes shimmer {
|
||||
0% { background-position: 200% 0; }
|
||||
100% { background-position: -200% 0; }
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.search-header h1 {
|
||||
font-size: 1.5rem;
|
||||
|
||||
@@ -3,6 +3,7 @@ import { DecimalPipe } from '@angular/common';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
import { RouterLink } from '@angular/router';
|
||||
import { ApiService, CartService } from '../../services';
|
||||
import { PrefetchService } from '../../services/prefetch.service';
|
||||
import { Item } from '../../models';
|
||||
import { Subject, Subscription } from 'rxjs';
|
||||
import { debounceTime, distinctUntilChanged } from 'rxjs/operators';
|
||||
@@ -11,6 +12,7 @@ import { LanguageService } from '../../services/language.service';
|
||||
import { LangRoutePipe } from '../../pipes/lang-route.pipe';
|
||||
import { TranslatePipe } from '../../i18n/translate.pipe';
|
||||
import { TranslateService } from '../../i18n/translate.service';
|
||||
import { SEARCH_DEBOUNCE_MS, ITEMS_PER_PAGE, SCROLL_THRESHOLD_PX, SCROLL_DEBOUNCE_MS } from '../../config/constants';
|
||||
|
||||
@Component({
|
||||
selector: 'app-search',
|
||||
@@ -28,7 +30,7 @@ export class SearchComponent implements OnDestroy {
|
||||
totalResults = signal<number>(0);
|
||||
|
||||
private skip = 0;
|
||||
private readonly count = 50;
|
||||
private readonly count = ITEMS_PER_PAGE;
|
||||
private isLoadingMore = false;
|
||||
private searchSubject = new Subject<string>();
|
||||
private searchSubscription: Subscription;
|
||||
@@ -36,11 +38,12 @@ export class SearchComponent implements OnDestroy {
|
||||
|
||||
constructor(
|
||||
private apiService: ApiService,
|
||||
private cartService: CartService
|
||||
private cartService: CartService,
|
||||
private prefetchService: PrefetchService
|
||||
) {
|
||||
this.searchSubscription = this.searchSubject
|
||||
.pipe(
|
||||
debounceTime(300),
|
||||
debounceTime(SEARCH_DEBOUNCE_MS),
|
||||
distinctUntilChanged()
|
||||
)
|
||||
.subscribe(query => {
|
||||
@@ -64,7 +67,7 @@ export class SearchComponent implements OnDestroy {
|
||||
performSearch(query: string): void {
|
||||
if (!query.trim()) {
|
||||
this.items.set([]);
|
||||
this.hasMore.set(true);
|
||||
this.hasMore.set(false);
|
||||
this.totalResults.set(0);
|
||||
return;
|
||||
}
|
||||
@@ -120,12 +123,12 @@ export class SearchComponent implements OnDestroy {
|
||||
|
||||
this.scrollTimeout = setTimeout(() => {
|
||||
const scrollPosition = window.innerHeight + window.scrollY;
|
||||
const bottomPosition = document.documentElement.scrollHeight - 500;
|
||||
const bottomPosition = document.documentElement.scrollHeight - SCROLL_THRESHOLD_PX;
|
||||
|
||||
if (scrollPosition >= bottomPosition && !this.loading() && this.hasMore()) {
|
||||
this.loadResults();
|
||||
}
|
||||
}, 100);
|
||||
}, SCROLL_DEBOUNCE_MS);
|
||||
}
|
||||
|
||||
addToCart(itemID: number, event: Event): void {
|
||||
@@ -134,6 +137,11 @@ export class SearchComponent implements OnDestroy {
|
||||
this.cartService.addItem(itemID);
|
||||
}
|
||||
|
||||
onItemHover(itemID: number): void {
|
||||
this.prefetchService.prefetchItem(itemID);
|
||||
}
|
||||
|
||||
readonly skeletonSlots = Array.from({ length: 8 });
|
||||
readonly getDiscountedPrice = getDiscountedPrice;
|
||||
readonly getMainImage = getMainImage;
|
||||
readonly trackByItemId = trackByItemId;
|
||||
|
||||
@@ -7,19 +7,30 @@ import { LanguageService } from '../services/language.service';
|
||||
})
|
||||
export class LangRoutePipe implements PipeTransform {
|
||||
private langService = inject(LanguageService);
|
||||
private lastLang = '';
|
||||
private lastInput: unknown = null;
|
||||
private lastResult: string | (string | number)[] = '';
|
||||
|
||||
transform(value: string | (string | number)[]): string | (string | number)[] {
|
||||
const lang = this.langService.currentLanguage();
|
||||
|
||||
// Short-circuit if nothing changed
|
||||
if (lang === this.lastLang && value === this.lastInput) {
|
||||
return this.lastResult;
|
||||
}
|
||||
|
||||
this.lastLang = lang;
|
||||
this.lastInput = value;
|
||||
|
||||
if (typeof value === 'string') {
|
||||
return value === '/' ? `/${lang}` : `/${lang}${value}`;
|
||||
}
|
||||
|
||||
if (Array.isArray(value) && value.length > 0) {
|
||||
this.lastResult = value === '/' ? `/${lang}` : `/${lang}${value}`;
|
||||
} else if (Array.isArray(value) && value.length > 0) {
|
||||
const [first, ...rest] = value;
|
||||
return [`/${lang}${first}`, ...rest];
|
||||
this.lastResult = [`/${lang}${first}`, ...rest];
|
||||
} else {
|
||||
this.lastResult = value;
|
||||
}
|
||||
|
||||
return value;
|
||||
return this.lastResult;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { HttpClient, HttpParams } from '@angular/common/http';
|
||||
import { Observable } from 'rxjs';
|
||||
import { map } from 'rxjs/operators';
|
||||
import { Observable, timer } from 'rxjs';
|
||||
import { map, retry } from 'rxjs/operators';
|
||||
import { Category, Item, Subcategory } from '../models';
|
||||
import { environment } from '../../environments/environment';
|
||||
|
||||
@@ -11,8 +11,34 @@ import { environment } from '../../environments/environment';
|
||||
export class ApiService {
|
||||
private readonly baseUrl = environment.apiUrl;
|
||||
|
||||
private readonly retryConfig = {
|
||||
count: 2,
|
||||
delay: (error: unknown, retryCount: number) => timer(Math.pow(2, retryCount) * 500)
|
||||
};
|
||||
|
||||
constructor(private http: HttpClient) {}
|
||||
|
||||
/** Map API language codes (RU/EN/AM) → frontend codes (ru/en/hy) */
|
||||
private normalizeLang(apiLang: string): string {
|
||||
const map: Record<string, string> = { 'RU': 'ru', 'EN': 'en', 'AM': 'hy' };
|
||||
return map[apiLang] || apiLang.toLowerCase();
|
||||
}
|
||||
|
||||
/** Convert Go-style hex colour (0xfffca0) → CSS hex (#fffca0) */
|
||||
private normalizeColor(c: string): string {
|
||||
if (!c) return '';
|
||||
return c.startsWith('0x') ? '#' + c.slice(2) : c;
|
||||
}
|
||||
|
||||
/** Resolve relative image URLs (e.g. ./images/x.webp) against site origin */
|
||||
private resolveImageUrl(url: string): string {
|
||||
if (!url) return '';
|
||||
if (url.startsWith('http://') || url.startsWith('https://') || url.startsWith('/')) return url;
|
||||
const origin = `https://${environment.domain}`;
|
||||
if (url.startsWith('./')) return `${origin}/${url.slice(2)}`;
|
||||
return `${origin}/${url}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalize an item from the API response — supports both
|
||||
* legacy marketplace format and the new backOffice API format.
|
||||
@@ -21,6 +47,26 @@ export class ApiService {
|
||||
const { partnerID, ...rest } = raw;
|
||||
const item: Item = { ...rest };
|
||||
|
||||
// Extract price/currency/remaining/colour/size from itemDetails[]
|
||||
// Note: Go struct tag is "itemdetails" but actual API may send "itemDetails"
|
||||
const details = raw.itemDetails || raw.itemdetails;
|
||||
if (details && Array.isArray(details) && details.length > 0) {
|
||||
const detail = details[0];
|
||||
item.itemDetails = details.map((d: any) => ({
|
||||
...d,
|
||||
colour: this.normalizeColor(d.colour || d.color || ''),
|
||||
color: undefined,
|
||||
}));
|
||||
if (item.price == null || item.price === 0) item.price = detail.price;
|
||||
if (!item.currency) item.currency = detail.currency;
|
||||
if (!item.colour) item.colour = this.normalizeColor(detail.colour || detail.color || '');
|
||||
if (!item.size) item.size = detail.size || '';
|
||||
// Use remaining from detail for stock level
|
||||
if (raw.remaining == null && detail.remaining != null) {
|
||||
(raw as any).remaining = detail.remaining;
|
||||
}
|
||||
}
|
||||
|
||||
// Map backOffice string id → legacy numeric itemID
|
||||
if (raw.id != null && raw.itemID == null) {
|
||||
item.id = String(raw.id);
|
||||
@@ -32,13 +78,16 @@ export class ApiService {
|
||||
item.photos = raw.imgs.map((url: string) => ({ url }));
|
||||
}
|
||||
// Normalize photo type: API sends type='video'|'photo', template checks .video
|
||||
// Also resolve relative URLs (e.g. ./images/x.webp) against API base
|
||||
if (item.photos) {
|
||||
item.photos = item.photos.map((p: any) => ({
|
||||
...p,
|
||||
url: this.resolveImageUrl(p.url),
|
||||
video: p.video || (p.type === 'video' ? p.url : undefined),
|
||||
}));
|
||||
}
|
||||
item.imgs = raw.imgs || raw.photos?.map((p: any) => p.url) || [];
|
||||
item.imgs = raw.imgs?.map((u: string) => this.resolveImageUrl(u))
|
||||
|| item.photos?.map((p: any) => p.url) || [];
|
||||
|
||||
// Map backOffice description (key-value array) → legacy description string
|
||||
if (Array.isArray(raw.description)) {
|
||||
@@ -49,31 +98,31 @@ export class ApiService {
|
||||
}
|
||||
|
||||
// Map backend names[] → translations (multi-lang name support)
|
||||
// Note: API has typo "valuue" in some responses, handle both
|
||||
if (raw.names && Array.isArray(raw.names)) {
|
||||
item.names = raw.names;
|
||||
if (!item.translations) item.translations = {};
|
||||
for (const entry of raw.names) {
|
||||
if (!item.translations[entry.language]) item.translations[entry.language] = {};
|
||||
item.translations[entry.language].name = entry.value;
|
||||
const lang = this.normalizeLang(entry.language);
|
||||
const val = entry.value || entry.valuue || '';
|
||||
if (val) {
|
||||
if (!item.translations[lang]) item.translations[lang] = {};
|
||||
item.translations[lang].name = val;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Map backend descriptions[] → translations (multi-lang descriptions)
|
||||
if (raw.descriptions && Array.isArray(raw.descriptions)) {
|
||||
item.descriptions = raw.descriptions;
|
||||
if (!item.translations) item.translations = {};
|
||||
for (const entry of raw.descriptions) {
|
||||
if (!item.translations[entry.language]) item.translations[entry.language] = {};
|
||||
item.translations[entry.language].simpleDescription = entry.value;
|
||||
// Fallback: if top-level name is missing, use first available translation
|
||||
if (!item.name && raw.names.length > 0) {
|
||||
const ruName = raw.names.find((n: any) => n.language === 'RU' || n.language === 'ru');
|
||||
item.name = ruName?.value || ruName?.valuue || raw.names[0].value || raw.names[0].valuue || '';
|
||||
}
|
||||
}
|
||||
|
||||
// Preserve attributes from backend
|
||||
item.attributes = raw.attributes || [];
|
||||
|
||||
// Preserve colour & size
|
||||
item.colour = raw.colour || '';
|
||||
item.size = raw.size || '';
|
||||
// Preserve colour & size (only if not already set from itemDetails)
|
||||
if (!item.colour) item.colour = this.normalizeColor(raw.colour || '');
|
||||
if (!item.size) item.size = raw.size || '';
|
||||
|
||||
// Map backOffice comments → legacy callbacks
|
||||
if (raw.comments && (!raw.callbacks || raw.callbacks.length === 0)) {
|
||||
@@ -102,8 +151,12 @@ export class ApiService {
|
||||
item.rating = item.rating || 0;
|
||||
|
||||
// Defaults
|
||||
item.name = item.name || '';
|
||||
item.price = item.price ?? 0;
|
||||
item.discount = item.discount || 0;
|
||||
item.remainings = item.remainings || (raw.quantity != null
|
||||
item.remainings = item.remainings || (raw.remaining != null
|
||||
? (raw.remaining <= 0 ? 'out' : raw.remaining <= 5 ? 'low' : raw.remaining <= 20 ? 'medium' : 'high')
|
||||
: raw.quantity != null
|
||||
? (raw.quantity <= 0 ? 'out' : raw.quantity <= 5 ? 'low' : raw.quantity <= 20 ? 'medium' : 'high')
|
||||
: 'high');
|
||||
item.currency = item.currency || 'RUB';
|
||||
@@ -115,6 +168,16 @@ export class ApiService {
|
||||
item.translations = item.translations || raw.translations || {};
|
||||
item.visible = raw.visible ?? true;
|
||||
item.priority = raw.priority ?? 0;
|
||||
item.visits = raw.visits ?? 0;
|
||||
|
||||
// Map question like/dislike → upvotes/downvotes
|
||||
if (item.questions) {
|
||||
item.questions = item.questions.map((q: any) => ({
|
||||
...q,
|
||||
upvotes: q.upvotes ?? q.like ?? 0,
|
||||
downvotes: q.downvotes ?? q.dislike ?? 0,
|
||||
}));
|
||||
}
|
||||
|
||||
return item;
|
||||
}
|
||||
@@ -144,9 +207,41 @@ export class ApiService {
|
||||
}
|
||||
cat.img = raw.img || raw.icon;
|
||||
|
||||
// Resolve relative icon/image URLs
|
||||
if (cat.icon) cat.icon = this.resolveImageUrl(cat.icon);
|
||||
if (cat.img) cat.img = this.resolveImageUrl(cat.img);
|
||||
|
||||
// Map backend wideicon → wideBanner
|
||||
if (raw.wideicon && !cat.wideBanner) {
|
||||
cat.wideBanner = raw.wideicon;
|
||||
}
|
||||
|
||||
cat.parentID = raw.parentID ?? 0;
|
||||
cat.visible = raw.visible ?? true;
|
||||
cat.priority = raw.priority ?? 0;
|
||||
cat.itemCount = raw.itemCount ?? raw.ItemsCount ?? 0;
|
||||
cat.categoriesCount = raw.categoriesCount ?? raw.CategoriesCount ?? 0;
|
||||
|
||||
// Map backend names[] → translations (multi-lang name support)
|
||||
// Note: API has typo "valuue" in some responses, handle both
|
||||
if (raw.names && Array.isArray(raw.names)) {
|
||||
cat.names = raw.names;
|
||||
cat.translations = cat.translations || {};
|
||||
for (const entry of raw.names) {
|
||||
const lang = this.normalizeLang(entry.language);
|
||||
const val = entry.value || entry.valuue || '';
|
||||
if (val) {
|
||||
if (!cat.translations[lang]) cat.translations[lang] = {};
|
||||
cat.translations[lang].name = val;
|
||||
}
|
||||
}
|
||||
// Fallback: if top-level name is missing, use first available translation
|
||||
if (!cat.name && raw.names.length > 0) {
|
||||
const ruName = raw.names.find((n: any) => n.language === 'RU' || n.language === 'ru');
|
||||
cat.name = ruName?.value || ruName?.valuue || raw.names[0].value || raw.names[0].valuue || '';
|
||||
}
|
||||
}
|
||||
cat.name = cat.name || '';
|
||||
|
||||
if (raw.subcategories && Array.isArray(raw.subcategories)) {
|
||||
cat.subcategories = raw.subcategories;
|
||||
@@ -168,7 +263,7 @@ export class ApiService {
|
||||
|
||||
getCategories(): Observable<Category[]> {
|
||||
return this.http.get<any[]>(`${this.baseUrl}/category`)
|
||||
.pipe(map(cats => this.normalizeCategories(cats)));
|
||||
.pipe(retry(this.retryConfig), map(cats => this.normalizeCategories(cats)));
|
||||
}
|
||||
|
||||
getCategoryItems(categoryID: number, count: number = 50, skip: number = 0): Observable<Item[]> {
|
||||
@@ -176,21 +271,48 @@ export class ApiService {
|
||||
.set('count', count.toString())
|
||||
.set('skip', skip.toString());
|
||||
return this.http.get<any[]>(`${this.baseUrl}/category/${categoryID}`, { params })
|
||||
.pipe(map(items => this.normalizeItems(items)));
|
||||
.pipe(retry(this.retryConfig), map(items => this.normalizeItems(items)));
|
||||
}
|
||||
|
||||
getItem(itemID: number): Observable<Item> {
|
||||
return this.http.get<any>(`${this.baseUrl}/item/${itemID}`)
|
||||
.pipe(map(item => this.normalizeItem(item)));
|
||||
return this.http.get<any>(`${this.baseUrl}/items/${itemID}`)
|
||||
.pipe(retry(this.retryConfig), map(item => this.normalizeItem(item)));
|
||||
}
|
||||
|
||||
searchItems(search: string, count: number = 50, skip: number = 0): Observable<{ items: Item[], total: number }> {
|
||||
const params = new HttpParams()
|
||||
searchItems(
|
||||
search: string,
|
||||
count: number = 50,
|
||||
skip: number = 0,
|
||||
options?: {
|
||||
categoryIDs?: number[];
|
||||
minPrice?: number;
|
||||
maxPrice?: number;
|
||||
tag?: string;
|
||||
sort?: 'relevance' | 'price_asc' | 'price_desc' | 'popular' | 'rating';
|
||||
}
|
||||
): Observable<{ items: Item[], total: number }> {
|
||||
let params = new HttpParams()
|
||||
.set('search', search)
|
||||
.set('count', count.toString())
|
||||
.set('skip', skip.toString());
|
||||
if (options?.categoryIDs?.length) {
|
||||
params = params.set('categoryIDs', options.categoryIDs.join(','));
|
||||
}
|
||||
if (options?.minPrice != null) {
|
||||
params = params.set('minPrice', options.minPrice.toString());
|
||||
}
|
||||
if (options?.maxPrice != null) {
|
||||
params = params.set('maxPrice', options.maxPrice.toString());
|
||||
}
|
||||
if (options?.tag) {
|
||||
params = params.set('tag', options.tag);
|
||||
}
|
||||
if (options?.sort) {
|
||||
params = params.set('sort', options.sort);
|
||||
}
|
||||
return this.http.get<any>(`${this.baseUrl}/searchitems`, { params })
|
||||
.pipe(
|
||||
retry(this.retryConfig),
|
||||
map(response => ({
|
||||
items: this.normalizeItems(response?.items || []),
|
||||
total: response?.total || 0
|
||||
@@ -198,21 +320,9 @@ export class ApiService {
|
||||
);
|
||||
}
|
||||
|
||||
addToCart(itemID: number, quantity: number = 1): Observable<{ message: string }> {
|
||||
return this.http.post<{ message: string }>(`${this.baseUrl}/cart`, { itemID, quantity });
|
||||
}
|
||||
|
||||
updateCartQuantity(itemID: number, quantity: number): Observable<{ message: string }> {
|
||||
return this.http.patch<{ message: string }>(`${this.baseUrl}/cart`, { itemID, quantity });
|
||||
}
|
||||
|
||||
removeFromCart(itemIDs: number[]): Observable<{ message: string }> {
|
||||
return this.http.delete<{ message: string }>(`${this.baseUrl}/cart`, { body: itemIDs });
|
||||
}
|
||||
|
||||
getCart(): Observable<Item[]> {
|
||||
return this.http.get<any[]>(`${this.baseUrl}/cart`)
|
||||
.pipe(map(items => this.normalizeItems(items)));
|
||||
// Cart operations — spec uses websession-based paths
|
||||
addToCart(sessionId: string, items: Array<{ itemID: number; quantity: number; colour?: string; size?: string; price?: number }>): Observable<any> {
|
||||
return this.http.post<any>(`${this.baseUrl}/websession/${sessionId}`, items);
|
||||
}
|
||||
|
||||
// Review submission
|
||||
@@ -220,39 +330,42 @@ export class ApiService {
|
||||
itemID: number;
|
||||
rating: number;
|
||||
comment: string;
|
||||
username: string | null;
|
||||
userId: number | null;
|
||||
sessionID: string;
|
||||
timestamp: string;
|
||||
}): Observable<{ message: string }> {
|
||||
return this.http.post<{ message: string }>(`${this.baseUrl}/comment`, reviewData);
|
||||
const { itemID, ...body } = reviewData;
|
||||
return this.http.post<{ message: string }>(`${this.baseUrl}/items/${itemID}/callback`, body);
|
||||
}
|
||||
|
||||
// Payment - SBP Integration
|
||||
createPayment(paymentData: {
|
||||
amount: number;
|
||||
currency: string;
|
||||
siteuserID: string;
|
||||
siteorderID: string;
|
||||
redirectUrl: string;
|
||||
telegramUsername: string;
|
||||
items: Array<{ itemID: number; price: number; name: string }>;
|
||||
}): Observable<{
|
||||
// Question submission — spec path has typo "questiion"
|
||||
submitQuestion(questionData: {
|
||||
itemID: number;
|
||||
question: string;
|
||||
sessionID: string;
|
||||
timestamp: string;
|
||||
}): Observable<{ message: string }> {
|
||||
const { itemID, ...body } = questionData;
|
||||
return this.http.post<{ message: string }>(`${this.baseUrl}/items/${itemID}/questiion`, body);
|
||||
}
|
||||
|
||||
// Payment - SBP Integration via websession QR
|
||||
createPayment(sessionId: string): Observable<{
|
||||
qrId: string;
|
||||
qrStatus: string;
|
||||
qrExpirationDate: string;
|
||||
payload: string;
|
||||
Payload: string;
|
||||
qrUrl: string;
|
||||
}> {
|
||||
return this.http.post<{
|
||||
qrId: string;
|
||||
qrStatus: string;
|
||||
qrExpirationDate: string;
|
||||
payload: string;
|
||||
Payload: string;
|
||||
qrUrl: string;
|
||||
}>(`${this.baseUrl}/cart`, paymentData);
|
||||
}>(`${this.baseUrl}/websession/${sessionId}/qr`, {});
|
||||
}
|
||||
|
||||
checkPaymentStatus(qrId: string): Observable<{
|
||||
checkPaymentStatus(sessionId: string, qrId: string): Observable<{
|
||||
additionalInfo: string;
|
||||
paymentPurpose: string;
|
||||
amount: number;
|
||||
@@ -265,7 +378,6 @@ export class ApiService {
|
||||
transactionDate: string;
|
||||
transactionId: number;
|
||||
qrExpirationDate: string;
|
||||
phoneNumber: string;
|
||||
}> {
|
||||
return this.http.get<{
|
||||
additionalInfo: string;
|
||||
@@ -280,8 +392,7 @@ export class ApiService {
|
||||
transactionDate: string;
|
||||
transactionId: number;
|
||||
qrExpirationDate: string;
|
||||
phoneNumber: string;
|
||||
}>(`${this.baseUrl}/qr/payment/${qrId}`);
|
||||
}>(`${this.baseUrl}/websession/${sessionId}/${qrId}`);
|
||||
}
|
||||
|
||||
submitPurchaseEmail(emailData: {
|
||||
@@ -297,7 +408,7 @@ export class ApiService {
|
||||
if (categoryID) {
|
||||
params = params.set('category', categoryID.toString());
|
||||
}
|
||||
return this.http.get<any[]>(`${this.baseUrl}/randomitems`, { params })
|
||||
.pipe(map(items => this.normalizeItems(items)));
|
||||
return this.http.get<any[]>(`${this.baseUrl}/items/randomitems`, { params })
|
||||
.pipe(retry(this.retryConfig), map(items => this.normalizeItems(items)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Injectable, signal, computed } from '@angular/core';
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { Observable, of, catchError, map, tap } from 'rxjs';
|
||||
import { AuthSession, AuthStatus } from '../models/auth.model';
|
||||
import { AuthSession, AuthStatus, QrPollResponse } from '../models/auth.model';
|
||||
import { environment } from '../../environments/environment';
|
||||
|
||||
@Injectable({
|
||||
@@ -72,7 +72,7 @@ export class AuthService {
|
||||
|
||||
/** Generate the Telegram login URL for bot-based auth */
|
||||
getTelegramLoginUrl(): string {
|
||||
const botUsername = (environment as Record<string, unknown>)['telegramBot'] as string || 'dexarmarket_bot';
|
||||
const botUsername = (environment as Record<string, unknown>)['telegramBot'] as string || 'DexarSupport_bot';
|
||||
const callbackUrl = encodeURIComponent(`${this.apiUrl}/auth/telegram/callback`);
|
||||
return `https://t.me/${botUsername}?start=auth_${callbackUrl}`;
|
||||
}
|
||||
@@ -82,6 +82,34 @@ export class AuthService {
|
||||
return this.getTelegramLoginUrl();
|
||||
}
|
||||
|
||||
/** Create a one-time QR login token via backend */
|
||||
createQrToken(): Observable<{ token: string; url: string }> {
|
||||
return this.http.post<{ token: string; url: string }>(
|
||||
`${this.apiUrl}/auth/qr/create`,
|
||||
{},
|
||||
{ withCredentials: true }
|
||||
);
|
||||
}
|
||||
|
||||
/** Poll the QR token status (pending → confirmed / expired) */
|
||||
pollQrToken(token: string): Observable<QrPollResponse> {
|
||||
return this.http.get<QrPollResponse>(
|
||||
`${this.apiUrl}/auth/qr/poll`,
|
||||
{
|
||||
params: { token },
|
||||
withCredentials: true,
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/** Sync local cart to the backend session after login */
|
||||
syncCart(sessionId: string, items: Array<{ itemID: number; quantity: number; colour?: string; size?: string; price?: number }>): Observable<unknown> {
|
||||
if (!items.length) return of(null);
|
||||
return this.http.post(`${this.apiUrl}/websession/${sessionId}`, items, {
|
||||
withCredentials: true,
|
||||
}).pipe(catchError(() => of(null)));
|
||||
}
|
||||
|
||||
/** Show login dialog (called when user tries to pay without being logged in) */
|
||||
requestLogin(): void {
|
||||
this.showLoginSignal.set(true);
|
||||
|
||||
@@ -13,6 +13,7 @@ export class CartService {
|
||||
private cartItems = signal<CartItem[]>([]);
|
||||
private isTelegram = typeof window !== 'undefined' && !!window.Telegram?.WebApp;
|
||||
private addingItems = new Set<number>();
|
||||
private initialized = false;
|
||||
|
||||
items = this.cartItems.asReadonly();
|
||||
itemCount = computed(() => {
|
||||
@@ -31,10 +32,12 @@ export class CartService {
|
||||
constructor(private apiService: ApiService) {
|
||||
this.loadCart();
|
||||
|
||||
// Auto-save whenever cart changes
|
||||
// Auto-save whenever cart changes (skip the initial empty state)
|
||||
effect(() => {
|
||||
const items = this.cartItems();
|
||||
this.saveToStorage(items);
|
||||
if (this.initialized) {
|
||||
this.saveToStorage(items);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -67,9 +70,11 @@ export class CartService {
|
||||
// No data in CloudStorage, try localStorage
|
||||
this.loadFromLocalStorage();
|
||||
}
|
||||
this.initialized = true;
|
||||
});
|
||||
} else {
|
||||
this.loadFromLocalStorage();
|
||||
this.initialized = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -98,7 +103,7 @@ export class CartService {
|
||||
return false;
|
||||
}
|
||||
|
||||
addItem(itemID: number, quantity: number = 1): void {
|
||||
addItem(itemID: number, quantity: number = 1, variant?: { colour?: string; size?: string; price?: number; currency?: string }): void {
|
||||
// Prevent duplicate API calls for same item
|
||||
if (this.addingItems.has(itemID)) return;
|
||||
|
||||
@@ -113,7 +118,14 @@ export class CartService {
|
||||
this.addingItems.add(itemID);
|
||||
this.apiService.getItem(itemID).subscribe({
|
||||
next: (item) => {
|
||||
const cartItem: CartItem = { ...item, quantity };
|
||||
const cartItem: CartItem = {
|
||||
...item,
|
||||
quantity,
|
||||
...(variant?.colour != null && { colour: variant.colour }),
|
||||
...(variant?.size != null && { size: variant.size }),
|
||||
...(variant?.price != null && { price: variant.price }),
|
||||
...(variant?.currency != null && { currency: variant.currency }),
|
||||
};
|
||||
this.cartItems.set([...this.cartItems(), cartItem]);
|
||||
this.addingItems.delete(itemID);
|
||||
},
|
||||
|
||||
15
src/app/services/prefetch.service.ts
Normal file
15
src/app/services/prefetch.service.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { ApiService } from './api.service';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class PrefetchService {
|
||||
private prefetched = new Set<number>();
|
||||
|
||||
constructor(private api: ApiService) {}
|
||||
|
||||
prefetchItem(itemID: number): void {
|
||||
if (this.prefetched.has(itemID)) return;
|
||||
this.prefetched.add(itemID);
|
||||
this.api.getItem(itemID).subscribe();
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Injectable, inject } from '@angular/core';
|
||||
import { Injectable, inject, DOCUMENT } from '@angular/core';
|
||||
import { Meta, Title } from '@angular/platform-browser';
|
||||
import { environment } from '../../environments/environment';
|
||||
import { Item } from '../models';
|
||||
@@ -10,6 +10,7 @@ import { getDiscountedPrice, getMainImage } from '../utils/item.utils';
|
||||
export class SeoService {
|
||||
private meta = inject(Meta);
|
||||
private title = inject(Title);
|
||||
private doc = inject(DOCUMENT);
|
||||
|
||||
private readonly siteUrl = `https://${environment.domain}`;
|
||||
private readonly siteName = environment.brandFullName;
|
||||
@@ -18,13 +19,14 @@ export class SeoService {
|
||||
* Set Open Graph & Twitter Card meta tags for a product/item page.
|
||||
*/
|
||||
setItemMeta(item: Item): void {
|
||||
const price = item.discount > 0 ? getDiscountedPrice(item) : item.price;
|
||||
const price = item.discount > 0 ? getDiscountedPrice(item) : (item.price ?? 0);
|
||||
const imageUrl = this.resolveUrl(getMainImage(item));
|
||||
const itemUrl = `${this.siteUrl}/item/${item.itemID}`;
|
||||
const description = this.truncate(this.stripHtml(item.description), 160);
|
||||
const titleText = `${item.name} — ${this.siteName}`;
|
||||
const description = this.truncate(this.stripHtml(item.description || ''), 160);
|
||||
const titleText = `${item.name || 'Product'} — ${this.siteName}`;
|
||||
|
||||
this.title.setTitle(titleText);
|
||||
this.setCanonical(itemUrl);
|
||||
|
||||
this.setOrUpdate([
|
||||
// Open Graph
|
||||
@@ -81,6 +83,7 @@ export class SeoService {
|
||||
// Remove product-specific tags
|
||||
this.meta.removeTag("property='product:price:amount'");
|
||||
this.meta.removeTag("property='product:price:currency'");
|
||||
this.removeCanonical();
|
||||
}
|
||||
|
||||
private setOrUpdate(tags: Array<{ property?: string; name?: string; content: string }>): void {
|
||||
@@ -114,4 +117,19 @@ export class SeoService {
|
||||
if (!text || text.length <= maxLength) return text || '';
|
||||
return text.substring(0, maxLength - 1) + '…';
|
||||
}
|
||||
|
||||
private setCanonical(url: string): void {
|
||||
this.removeCanonical();
|
||||
const link = this.doc.createElement('link');
|
||||
link.setAttribute('rel', 'canonical');
|
||||
link.setAttribute('href', url);
|
||||
this.doc.head.appendChild(link);
|
||||
}
|
||||
|
||||
private removeCanonical(): void {
|
||||
const existing = this.doc.head.querySelector('link[rel="canonical"]');
|
||||
if (existing) {
|
||||
this.doc.head.removeChild(existing);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { Item } from '../models';
|
||||
import { Category } from '../models/category.model';
|
||||
|
||||
export function getDiscountedPrice(item: Item): number {
|
||||
return item.price * (1 - (item.discount || 0) / 100);
|
||||
@@ -69,24 +70,37 @@ export function getTranslatedField(
|
||||
field: 'name' | 'simpleDescription',
|
||||
lang: string
|
||||
): string {
|
||||
// 1. Check translations map (backOffice format)
|
||||
// 1. Check translations map (already normalized to frontend codes)
|
||||
const translation = item.translations?.[lang];
|
||||
if (translation && translation[field]) {
|
||||
return translation[field]!;
|
||||
}
|
||||
|
||||
// 2. Check names[]/descriptions[] arrays (backend API format)
|
||||
// 2. Check names[]/descriptions[] arrays (may have API codes: RU/EN/AM)
|
||||
// Note: API has typo "valuue" in some responses — handle both
|
||||
if (field === 'name' && item.names?.length) {
|
||||
const entry = item.names.find(n => n.language === lang);
|
||||
if (entry) return entry.value;
|
||||
const entry = item.names.find(n => n.language === lang || n.language === lang.toUpperCase() || (lang === 'hy' && n.language === 'AM'));
|
||||
const val = entry?.value || (entry as any)?.valuue || '';
|
||||
if (val) return val;
|
||||
}
|
||||
if (field === 'simpleDescription' && item.descriptions?.length) {
|
||||
const entry = item.descriptions.find(d => d.language === lang);
|
||||
if (entry) return entry.value;
|
||||
}
|
||||
|
||||
// 3. Fallback to base field
|
||||
if (field === 'name') return item.name;
|
||||
if (field === 'simpleDescription') return item.simpleDescription || item.description || '';
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get translated category name for the current language.
|
||||
*/
|
||||
export function getTranslatedCategoryName(cat: Category, lang: string): string {
|
||||
const translation = cat.translations?.[lang];
|
||||
if (translation?.name) return translation.name;
|
||||
|
||||
if (cat.names?.length) {
|
||||
const entry = cat.names.find(n => n.language === lang || n.language === lang.toUpperCase() || (lang === 'hy' && n.language === 'AM'));
|
||||
const val = entry?.value || (entry as any)?.valuue || '';
|
||||
if (val) return val;
|
||||
}
|
||||
|
||||
return cat.name || '';
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ export const environment = {
|
||||
brandName: 'novo Market',
|
||||
brandFullName: 'novo Market',
|
||||
theme: 'novo',
|
||||
apiUrl: 'https://api.novo.market:444',
|
||||
apiUrl: '/api',
|
||||
logo: '/assets/images/novo-logo.svg',
|
||||
contactEmail: 'info@novo.market',
|
||||
supportEmail: 'info@novo.market',
|
||||
@@ -12,8 +12,8 @@ export const environment = {
|
||||
telegram: '@novomarket',
|
||||
telegramBot: 'novomarket_bot',
|
||||
phones: {
|
||||
armenia: '+374 98 731231',
|
||||
support: '+374 98 731231'
|
||||
russia: '+7 916 109 10 32',
|
||||
support: '+7 916 109 10 32'
|
||||
},
|
||||
useMockData: false
|
||||
};
|
||||
|
||||
@@ -4,7 +4,7 @@ export const environment = {
|
||||
brandName: 'novo Market',
|
||||
brandFullName: 'novo Market',
|
||||
theme: 'novo',
|
||||
apiUrl: 'https://api.novo.market:444',
|
||||
apiUrl: '/api',
|
||||
logo: '/assets/images/novo-logo.svg',
|
||||
contactEmail: 'info@novo.market',
|
||||
supportEmail: 'info@novo.market',
|
||||
@@ -12,8 +12,8 @@ export const environment = {
|
||||
telegram: '@novomarket',
|
||||
telegramBot: 'novomarket_bot',
|
||||
phones: {
|
||||
armenia: '+374 98 731231',
|
||||
support: '+374 98 731231'
|
||||
russia: '+7 916 109 10 32',
|
||||
support: '+7 916 109 10 32'
|
||||
},
|
||||
useMockData: true
|
||||
useMockData: false
|
||||
};
|
||||
|
||||
@@ -10,7 +10,7 @@ export const environment = {
|
||||
supportEmail: 'info@dexarmarket.ru',
|
||||
domain: 'dexarmarket.ru',
|
||||
telegram: '@dexarmarket',
|
||||
telegramBot: 'dexarmarket_bot',
|
||||
telegramBot: 'DexarSupport_bot',
|
||||
phones: {
|
||||
russia: '+7 (926) 459-31-57',
|
||||
armenia: '+374 94 86 18 16'
|
||||
|
||||
@@ -11,7 +11,7 @@ export const environment = {
|
||||
supportEmail: 'info@dexarmarket.ru',
|
||||
domain: 'dexarmarket.ru',
|
||||
telegram: '@dexarmarket',
|
||||
telegramBot: 'dexarmarket_bot',
|
||||
telegramBot: 'DexarSupport_bot',
|
||||
phones: {
|
||||
russia: '+7 (926) 459-31-57',
|
||||
armenia: '+374 94 86 18 16'
|
||||
|
||||
4
start
4
start
@@ -1,2 +1,2 @@
|
||||
pm2 start "ng serve --configuration=novo --host 127.0.0.1 --port 4000" --name novo-market
|
||||
pm2 start "ng serve --host 127.0.0.1 --port 3000" --name dexar-market
|
||||
pm2 start "ng serve --configuration=novo --host 127.0.0.1 --port 4010" --name novo-market
|
||||
pm2 start "ng serve --host 127.0.0.1 --port 4001" --name dexar-market
|
||||
|
||||
Reference in New Issue
Block a user