-
-
-
-
-
- {{ summary.total_users }}
Всего клиентов
-
-
- {{ "%.2f"|format(summary.total_bonuses|float) }}
Всего бонусов
-
-
- {{ "%.2f"|format(summary.total_debts|float) }}
Всего долгов
-
-
- {{ summary.users_with_debt }}
Клиенты с долгом
-
-
+
-
-
-
- {% if users %}
-
- {% for user in users|sort(attribute='visited_at', reverse=true) %}
-
- {% else %}
-
-
- {% endfor %}
-
-
-
-
-
- {{ user.first_name or '' }} {{ user.last_name or '' }}
- @{{ user.username if user.username else user.phone_number }} | ID: {{ user.id }}
-
-
-
-
- Бонусы
{{ "%.2f"|format(user.bonuses|float) }}
Долг
{{ "%.2f"|format(user.debts|float if user.debts else 0) }}
-
- {% if user.telegram_id == None %}{% endif %}
-
- Пользователей пока нет.
- {% endif %} -
+
+
- {{ summary.total_users }}
+ Всего клиентов
-
-
Визитка
-
×
-
+
+
-
-
-
-
-
-
-
-
Бонусы
-
-
-
+
+
+
Бонусы
+
+
+
+
-
-
-
- Текущий баланс: 0.00
- Будет начислено (2%): +0.00
- Будет списано: -0.00
-
Итоговый баланс бонусов: 0.00
+
+
+
-
Долги
-
-
-
+
+
+
+
+
+ Текущий баланс: 0.00
+ Будет начислено (2%): +0.00
+ Будет списано: -0.00
+ +
Итоговый баланс бонусов: 0.00
+
+
Долги
+
+
+
+
-
-
-
- Текущий долг: 0.00
- Будет добавлено: +0.00
- Будет погашено: -0.00
-
Итоговый долг: 0.00
+
+
+
-
-
+
-
+
+
Текущий долг: 0.00
+ Будет добавлено: +0.00
+ Будет погашено: -0.00
+ +
Итоговый долг: 0.00
-
-
-
-
Создать накладную
-
-
-
-
-
-
- | Товар | Кол-во | Цена | Сумма |
|---|
-
+ Итого по накладной: 0.00
-
+
-
Накладная
+
+ {% for item in currentUserData.invoices | default([]) %}
+
-
+
+
+
+
+
+ {% endfor %}
Существующие накладные
-
-
+
+
+
+
+
Итоговая сумма накладной: 0.00
+
+ Общая история операций
+
+
+
+
-
+
+
+
×
-
-
-
-
+ Добавить нового клиента
+
+
+ Добавить нового клиента
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -952,38 +1390,46 @@ ADMIN_TEMPLATE = """
@app.route('/')
def index():
- page = request.args.get('page', 'home')
user_id_str = request.args.get('user_id_for_test')
- current_data = load_visitor_data()
+ current_visitor_data = load_visitor_data()
+ current_company_data = load_company_data()
user_data = {}
- if user_id_str and user_id_str in current_data:
- user_data = current_data[user_id_str]
+ if user_id_str and user_id_str in current_visitor_data:
+ user_data = current_visitor_data[user_id_str]
user_data['id'] = user_id_str
+
+ bonus_history = user_data.get('history', [])
+ for item in bonus_history:
+ item['transaction_type'] = 'bonus'
+
+ debt_history = user_data.get('debt_history', [])
+ for item in debt_history:
+ item['transaction_type'] = 'debt'
+
+ invoice_history = user_data.get('invoices', [])
+ for item in invoice_history:
+ item['transaction_type'] = 'invoice'
+
+ combined_history = sorted(
+ bonus_history + debt_history + invoice_history,
+ key=lambda x: x['date'],
+ reverse=True
+ )
+ user_data['combined_history'] = combined_history
else:
user_data = {
- "id": "N/A", "bonuses": 0, "debts": 0, "first_name": "Гость",
- "history": [], "debt_history": [], "invoices": []
+ "id": "N/A",
+ "bonuses": 0,
+ "debts": 0,
+ "history": [],
+ "debt_history": [],
+ "invoices": [],
+ "combined_history": []
}
- if page == 'card':
- org_info = load_org_info()
- return render_template_string(CARD_TEMPLATE, user=user_data, org_info=org_info, clean_phone=clean_phone_number)
-
- elif page == 'history':
- bonus_history = [dict(item, transaction_type='bonus') for item in user_data.get('history', [])]
- debt_history = [dict(item, transaction_type='debt') for item in user_data.get('debt_history', [])]
- user_data['combined_history'] = sorted(bonus_history + debt_history, key=lambda x: x['date'], reverse=True)
- return render_template_string(HISTORY_TEMPLATE, user=user_data)
-
- elif page == 'invoices':
- if 'invoices' in user_data and user_data['invoices']:
- user_data['invoices'] = sorted(user_data['invoices'], key=lambda x: x['date'], reverse=True)
- return render_template_string(INVOICES_TEMPLATE, user=user_data)
-
- else: # home
- return render_template_string(MAIN_TEMPLATE, user=user_data)
+ return render_template_string(TEMPLATE, user=user_data, company_info=current_company_data)
@app.route('/verify', methods=['POST'])
def verify_data():
@@ -994,187 +1440,334 @@ def verify_data():
return jsonify({"status": "error", "message": "Missing initData"}), 400
user_data_parsed, is_valid = verify_telegram_data(init_data_str)
- user_info_dict = json.loads(unquote(user_data_parsed['user'][0])) if user_data_parsed and 'user' in user_data_parsed else {}
- if is_valid and user_info_dict.get('id'):
- tg_user_id = str(user_info_dict['id'])
- now = datetime.now(BISHKEK_TZ)
- all_data = load_visitor_data()
-
- existing_user_key = next((k for k, v in all_data.items() if str(v.get('telegram_id')) == tg_user_id), None)
-
- if existing_user_key:
- user_entry = all_data[existing_user_key]
- user_entry.update({
- 'first_name': user_info_dict.get('first_name'), 'last_name': user_info_dict.get('last_name'),
- 'username': user_info_dict.get('username'), 'photo_url': user_info_dict.get('photo_url'),
- 'visited_at': now.timestamp(), 'visited_at_str': now.strftime('%Y-%m-%d %H:%M:%S')
- })
- user_id_to_save = existing_user_key
+ user_info_dict = {}
+ if user_data_parsed and 'user' in user_data_parsed:
+ try:
+ user_json_str = unquote(user_data_parsed['user'][0])
+ user_info_dict = json.loads(user_json_str)
+ except Exception as e:
+ logging.error(f"Could not parse user JSON: {e}")
+ user_info_dict = {}
+
+ if is_valid:
+ tg_user_id = user_info_dict.get('id')
+ if tg_user_id:
+ now = get_local_time()
+ all_data = load_visitor_data()
+
+ existing_user_key = None
+ for key, user_data_item in all_data.items():
+ if str(user_data_item.get('telegram_id')) == str(tg_user_id):
+ existing_user_key = key
+ break
+
+ if existing_user_key:
+ user_entry = all_data[existing_user_key]
+ user_entry.update({
+ 'first_name': user_info_dict.get('first_name'),
+ 'last_name': user_info_dict.get('last_name'),
+ 'username': user_info_dict.get('username'),
+ 'photo_url': user_info_dict.get('photo_url'),
+ 'language_code': user_info_dict.get('language_code'),
+ 'visited_at': now.timestamp(),
+ 'visited_at_str': format_local_time(now)
+ })
+ user_id_to_save = existing_user_key
+ else:
+ new_user_id = generate_unique_id(all_data)
+ user_entry = {
+ 'id': new_user_id,
+ 'telegram_id': tg_user_id,
+ 'first_name': user_info_dict.get('first_name'),
+ 'last_name': user_info_dict.get('last_name'),
+ 'username': user_info_dict.get('username'),
+ 'photo_url': user_info_dict.get('photo_url'),
+ 'language_code': user_info_dict.get('language_code'),
+ 'is_premium': user_info_dict.get('is_premium', False),
+ 'phone_number': None,
+ 'visited_at': now.timestamp(),
+ 'visited_at_str': format_local_time(now),
+ 'bonuses': 0,
+ 'history': [],
+ 'debts': 0,
+ 'debt_history': [],
+ 'invoices': []
+ }
+ user_id_to_save = new_user_id
+
+ save_visitor_data({user_id_to_save: user_entry})
+
+ return jsonify({"status": "ok", "verified": True, "user_id": user_id_to_save})
else:
- new_user_id = generate_unique_id(all_data)
- user_entry = {
- 'id': new_user_id, 'telegram_id': tg_user_id, 'bonuses': 0, 'history': [], 'debts': 0, 'debt_history': [], 'invoices': [],
- 'first_name': user_info_dict.get('first_name'), 'last_name': user_info_dict.get('last_name'),
- 'username': user_info_dict.get('username'), 'photo_url': user_info_dict.get('photo_url'),
- 'phone_number': None, 'visited_at': now.timestamp(), 'visited_at_str': now.strftime('%Y-%m-%d %H:%M:%S')
- }
- user_id_to_save = new_user_id
-
- save_visitor_data({user_id_to_save: user_entry})
- return jsonify({"status": "ok", "verified": True, "user_id": user_id_to_save})
+ return jsonify({"status": "error", "verified": True, "message": "User ID not found in parsed data"}), 400
else:
- return jsonify({"status": "error", "verified": is_valid, "message": "Invalid data or missing user ID"}), 403
+ logging.warning(f"Verification failed for user: {user_info_dict.get('id')}")
+ return jsonify({"status": "error", "verified": False, "message": "Invalid data"}), 403
+
except Exception as e:
+ logging.exception("Error in /verify endpoint")
return jsonify({"status": "error", "message": "Internal server error"}), 500
@app.route('/admin')
def admin_panel():
- current_data = load_visitor_data()
- org_info = load_org_info()
- users_list = [dict(v, id=k) for k, v in current_data.items()]
+ current_visitor_data = load_visitor_data()
+ current_company_data = load_company_data()
+ users_list = []
+ for user_id, user_data in current_visitor_data.items():
+ user_data['id'] = user_id
+ users_list.append(user_data)
+
+ total_users = len(users_list)
+ total_bonuses = sum(u.get('bonuses', 0) for u in users_list)
+ total_debts = sum(u.get('debts', 0) for u in users_list)
+ users_with_debt = sum(1 for u in users_list if u.get('debts', 0) > 0)
+
summary_stats = {
- "total_users": len(users_list),
- "total_bonuses": sum(u.get('bonuses', 0) for u in users_list),
- "total_debts": sum(u.get('debts', 0) for u in users_list),
- "users_with_debt": sum(1 for u in users_list if u.get('debts', 0) > 0)
+ "total_users": total_users,
+ "total_bonuses": total_bonuses,
+ "total_debts": total_debts,
+ "users_with_debt": users_with_debt
}
- return render_template_string(ADMIN_TEMPLATE, users=users_list, summary=summary_stats, org_info=org_info)
+
+ return render_template_string(ADMIN_TEMPLATE, users=users_list, summary=summary_stats, company_info=current_company_data)
-@app.route('/admin/update_organization_info', methods=['POST'])
-def update_organization_info():
- try:
- data = request.form
- phones = [p.strip() for p in data.get('phones', '').splitlines() if p.strip()]
- links_raw = [p.strip() for p in data.get('links', '').splitlines() if p.strip()]
- links = []
- for line in links_raw:
- parts = [p.strip() for p in line.split(',', 1)]
- if len(parts) == 2:
- links.append({"label": parts[0], "url": parts[1]})
-
- org_info = {
- "name": data.get('name', ''),
- "phones": phones,
- "address": data.get('address', ''),
- "links": links
- }
- save_org_info(org_info)
- return redirect(url_for('admin_panel'))
- except Exception:
- return "Error", 500
-
@app.route('/admin/add_client', methods=['POST'])
def add_client():
try:
data = request.get_json()
phone_number = data.get('phone_number')
first_name = data.get('first_name')
+
if not phone_number or not first_name:
return jsonify({"status": "error", "message": "Имя и номер телефона обязательны."}), 400
+
all_data = load_visitor_data()
- if any(u.get('phone_number') == phone_number for u in all_data.values()):
- return jsonify({"status": "error", "message": "Клиент с таким номером уже существует."}), 409
- now = datetime.now(BISHKEK_TZ)
+
+ for user in all_data.values():
+ if user.get('phone_number') == phone_number:
+ return jsonify({"status": "error", "message": "Клиент с таким номером телефона уже существует."}), 409
+
+ now = get_local_time()
new_id = generate_unique_id(all_data)
+
new_client = {
- 'id': new_id, 'telegram_id': None, 'first_name': first_name, 'phone_number': phone_number,
- 'bonuses': 0, 'history': [], 'debts': 0, 'debt_history': [], 'invoices': [],
- 'visited_at': now.timestamp(), 'visited_at_str': now.strftime('%Y-%m-%d %H:%M:%S'),
- 'last_name': None, 'username': None, 'photo_url': None
+ 'id': new_id,
+ 'telegram_id': None,
+ 'first_name': first_name,
+ 'last_name': None,
+ 'username': None,
+ 'photo_url': None,
+ 'language_code': 'ru',
+ 'is_premium': False,
+ 'phone_number': phone_number,
+ 'visited_at': now.timestamp(),
+ 'visited_at_str': format_local_time(now),
+ 'bonuses': 0,
+ 'history': [],
+ 'debts': 0,
+ 'debt_history': [],
+ 'invoices': []
}
+
save_visitor_data({new_id: new_client})
- return jsonify({"status": "ok", "message": "Клиент успешно добавлен!"}), 201
+
+ return jsonify({"status": "ok", "message": "Client added successfully"}), 201
+
except Exception as e:
+ logging.exception("Error in /admin/add_client endpoint")
return jsonify({"status": "error", "message": str(e)}), 500
@app.route('/admin/add_transaction', methods=['POST'])
def add_transaction():
try:
data = request.get_json()
- user_id, purchase, deduct = str(data.get('user_id')), float(data.get('purchase_amount', 0)), float(data.get('deduct_amount', 0))
- add_debt, repay_debt = float(data.get('add_debt_amount', 0)), float(data.get('repay_debt_amount', 0))
- all_data = load_visitor_data()
- if user_id not in all_data: return jsonify({"status": "error", "message": "User not found"}), 404
- user = all_data[user_id]
- now = datetime.now(BISHKEK_TZ)
+ user_id = data.get('user_id')
+ purchase_amount = float(data.get('purchase_amount', 0))
+ deduct_amount = float(data.get('deduct_amount', 0))
+ add_debt_amount = float(data.get('add_debt_amount', 0))
+ repay_debt_amount = float(data.get('repay_debt_amount', 0))
+ invoice_items = data.get('invoice_items', [])
+ invoice_total_amount = float(data.get('invoice_total_amount', 0))
+
+ if not user_id:
+ return jsonify({"status": "error", "message": "User ID is required"}), 400
- accrual_amount = purchase * 0.02
- new_balance = user.get('bonuses', 0) + accrual_amount
- if deduct > new_balance: return jsonify({"status": "error", "message": "Недостаточно бонусов для списания"}), 400
- user['bonuses'] = new_balance - deduct
+ user_id_str = str(user_id)
+ all_data = load_visitor_data()
+
+ if user_id_str not in all_data:
+ return jsonify({"status": "error", "message": "User not found"}), 404
+
+ user = all_data[user_id_str]
+ now = get_local_time()
+ now_iso = now.isoformat()
+ now_str = format_local_time(now)
- if accrual_amount > 0: user.setdefault('history', []).append({"type": "accrual", "amount": accrual_amount, "description": f"Начисление с покупки {purchase}", "date": now.isoformat(), "date_str": now.strftime('%Y-%m-%d %H:%M:%S')})
- if deduct > 0: user.setdefault('history', []).append({"type": "deduction", "amount": deduct, "description": "Списание бонусов", "date": now.isoformat(), "date_str": now.strftime('%Y-%m-%d %H:%M:%S')})
+ if deduct_amount > user.get('bonuses', 0):
+ return jsonify({"status": "error", "message": "Недостаточно бонусов для списания"}), 400
- if repay_debt > user.get('debts', 0): return jsonify({"status": "error", "message": "Сумма погашения превышает долг"}), 400
- user['debts'] = user.get('debts', 0) + add_debt - repay_debt
+ if repay_debt_amount > user.get('debts', 0):
+ return jsonify({"status": "error", "message": "Сумма погашения превышает текущий долг"}), 400
+
+ # Bonus operations
+ accrual_amount = purchase_amount * 0.02
+ user['bonuses'] = user.get('bonuses', 0) + accrual_amount - deduct_amount
+ if 'history' not in user or not isinstance(user['history'], list):
+ user['history'] = []
- if add_debt > 0: user.setdefault('debt_history', []).append({"type": "accrual", "amount": add_debt, "description": "Добавление долга", "date": now.isoformat(), "date_str": now.strftime('%Y-%m-%d %H:%M:%S')})
- if repay_debt > 0: user.setdefault('debt_history', []).append({"type": "payment", "amount": repay_debt, "description": "Погашение долга", "date": now.isoformat(), "date_str": now.strftime('%Y-%m-%d %H:%M:%S')})
+ if accrual_amount > 0:
+ user['history'].append({
+ "type": "accrual", "amount": accrual_amount,
+ "description": f"Начисление с покупки {purchase_amount}",
+ "date": now_iso, "date_str": now_str
+ })
+ if deduct_amount > 0:
+ user['history'].append({
+ "type": "deduction", "amount": deduct_amount,
+ "description": "Списание бонусов",
+ "date": now_iso, "date_str": now_str
+ })
+
+ # Debt operations
+ user['debts'] = user.get('debts', 0) + add_debt_amount - repay_debt_amount
+ if 'debt_history' not in user or not isinstance(user['debt_history'], list):
+ user['debt_history'] = []
+
+ if add_debt_amount > 0:
+ user['debt_history'].append({
+ "type": "accrual", "amount": add_debt_amount,
+ "description": "Добавление долга",
+ "date": now_iso, "date_str": now_str
+ })
+ if repay_debt_amount > 0:
+ user['debt_history'].append({
+ "type": "payment", "amount": repay_debt_amount,
+ "description": "Погашение долга",
+ "date": now_iso, "date_str": now_str
+ })
- save_visitor_data({user_id: user})
- return jsonify({"status": "ok", "message": "Операция успешна"}), 200
+ # Invoice operation
+ if invoice_items and invoice_total_amount > 0:
+ invoice_id = len(user.get('invoices', [])) + 1
+ new_invoice = {
+ "id": invoice_id,
+ "items": invoice_items,
+ "total_amount": invoice_total_amount,
+ "date": now_iso,
+ "date_str": now_str
+ }
+ if 'invoices' not in user or not isinstance(user['invoices'], list):
+ user['invoices'] = []
+ user['invoices'].append(new_invoice)
+
+ # Deduct invoice total from user's bonuses if they exist
+ if user['bonuses'] >= invoice_total_amount:
+ user['bonuses'] -= invoice_total_amount
+ user['history'].append({
+ "type": "deduction", "amount": invoice_total_amount,
+ "description": f"Оплата накладной #{invoice_id}",
+ "date": now_iso, "date_str": now_str
+ })
+ else:
+ # Optionally handle insufficient bonuses, maybe add to debt or inform user
+ logging.warning(f"User {user_id_str} has insufficient bonuses to pay for invoice #{invoice_id}.")
+ # For now, just record the invoice and don't deduct if bonuses are insufficient.
+ # A more complex system might add to debt here.
+ pass
+
+ save_visitor_data({user_id_str: user})
+
+ return jsonify({
+ "status": "ok", "message": "Transaction successful",
+ "new_balance": user['bonuses'], "new_debt": user['debts']
+ }), 200
+
except Exception as e:
+ logging.exception("Error in /admin/add_transaction endpoint")
return jsonify({"status": "error", "message": str(e)}), 500
-@app.route('/admin/add_invoice', methods=['POST'])
-def add_invoice():
+@app.route('/admin/update_company_data', methods=['POST'])
+def update_company_data():
try:
data = request.get_json()
- user_id = str(data.get('user_id'))
- items = data.get('items', [])
- if not user_id or not items:
- return jsonify({"status": "error", "message": "Требуется ID пользователя и товары"}), 400
-
- all_data = load_visitor_data()
- if user_id not in all_data:
- return jsonify({"status": "error", "message": "User not found"}), 404
-
- user = all_data[user_id]
- now = datetime.now(BISHKEK_TZ)
- invoice_id = f"{int(now.timestamp()) % 100000}{random.randint(10,99)}"
-
- total_amount = sum(float(item.get('quantity', 0)) * float(item.get('price_per_unit', 0)) for item in items)
-
- new_invoice = {
- "id": invoice_id,
- "date": now.isoformat(),
- "date_str": now.strftime('%Y-%m-%d %H:%M:%S'),
- "items": items,
- "total_amount": total_amount
+ company_name = data.get('name')
+ company_address = data.get('address')
+ phones = data.get('phones', [])
+ social_links = data.get('social_links', [])
+
+ if not company_name or not company_address:
+ return jsonify({"status": "error", "message": "Название компании и адрес обязательны."}), 400
+
+ updated_company_data = {
+ 'name': company_name,
+ 'address': company_address,
+ 'phones': phones,
+ 'social_links': social_links
}
- user.setdefault('invoices', []).append(new_invoice)
- save_visitor_data({user_id: user})
-
- return jsonify({"status": "ok", "message": "Накладная успешно сохранена!"}), 201
+ save_company_data(updated_company_data)
+ return jsonify({"status": "ok", "message": "Company data updated successfully"}), 200
+
except Exception as e:
+ logging.exception("Error in /admin/update_company_data endpoint")
return jsonify({"status": "error", "message": str(e)}), 500
@app.route('/admin/delete_client', methods=['POST'])
def delete_client():
try:
- user_id = str(request.get_json().get('user_id'))
- if not user_id: return jsonify({"status": "error", "message": "User ID is required"}), 400
+ data = request.get_json()
+ user_id = data.get('user_id')
+
+ if not user_id:
+ return jsonify({"status": "error", "message": "User ID is required"}), 400
+
+ user_id_str = str(user_id)
load_visitor_data()
+
with _data_lock:
- if user_id not in visitor_data_cache: return jsonify({"status": "error", "message": "User not found"}), 404
- if visitor_data_cache[user_id].get('telegram_id') is not None: return jsonify({"status": "error", "message": "Cannot delete a Telegram-linked user"}), 403
- del visitor_data_cache[user_id]
- with open(DATA_FILE, 'w', encoding='utf-8') as f:
- json.dump(visitor_data_cache, f, ensure_ascii=False, indent=4)
- upload_data_to_hf_async()
- return jsonify({"status": "ok", "message": "Клиент удален"}), 200
+ if user_id_str not in visitor_data_cache:
+ return jsonify({"status": "error", "message": "User not found"}), 404
+
+ user_to_delete = visitor_data_cache[user_id_str]
+ if user_to_delete.get('telegram_id') is not None:
+ return jsonify({"status": "error", "message": "Cannot delete a Telegram-linked user"}), 403
+
+ del visitor_data_cache[user_id_str]
+
+ try:
+ with open(DATA_FILE, 'w', encoding='utf-8') as f:
+ json.dump(visitor_data_cache, f, ensure_ascii=False, indent=4)
+ logging.info(f"User {user_id_str} deleted. Data saved to {DATA_FILE}.")
+ upload_data_to_hf_async()
+ except Exception as e:
+ logging.error(f"Error saving data after deletion: {e}")
+ return jsonify({"status": "error", "message": "Failed to save data after deletion"}), 500
+
+ return jsonify({"status": "ok", "message": "Client deleted successfully"}), 200
+
except Exception as e:
+ logging.exception("Error in /admin/delete_client endpoint")
return jsonify({"status": "error", "message": str(e)}), 500
if __name__ == '__main__':
- if HF_TOKEN_READ:
- download_files_from_hf()
+ print("--- BONUS SYSTEM SERVER ---")
+ print(f"Server starting on http://{HOST}:{PORT}")
+ if not HF_TOKEN_READ or not HF_TOKEN_WRITE:
+ print("WARNING: Hugging Face token(s) not set. Backup/restore functionality will be limited.")
+ else:
+ print("Attempting initial data download from Hugging Face...")
+ download_data_from_hf()
+
load_visitor_data()
- load_org_info()
+ load_company_data()
+
+ print("WARNING: The /admin route is NOT protected. Implement proper authentication for production.")
+
if HF_TOKEN_WRITE:
backup_thread = threading.Thread(target=periodic_backup, daemon=True)
backup_thread.start()
+ print("Periodic backup thread started (every hour).")
+
+ print("--- Server Ready ---")
app.run(host=HOST, port=PORT, debug=False)
\ No newline at end of file
+ ×
+
+
+ Редактировать визитную карточку
+
+
+
+
+
+
+
+
+
+
+
+ Телефоны
+
+
+
+
+ Ссылки
+
+
+
+
+
+
+