Compare commits

...

5 Commits

Author SHA1 Message Date
anhduy-tech
4acaa0bc3c changes 2026-04-07 10:56:08 +07:00
anhduy-tech
52977d0104 changes 2026-04-07 10:35:05 +07:00
Xuan Loi
dfc7914d3d changes 2026-04-02 14:35:38 +07:00
Xuan Loi
221dc0f1e1 x
Merge branch 'origin' of https://git.bigdatatech.vn/bigdatacloud/api into origin
2026-04-02 11:11:25 +07:00
Xuan Loi
3e78dde2e2 changes 2026-04-02 11:11:06 +07:00
32 changed files with 277 additions and 21 deletions

1
.env Normal file
View File

@@ -0,0 +1 @@
HCLOUD_TOKEN=RvGyXJLLmgGCnWM4EOZwFMYK4xfGvwmNCbkm8G1NzIp9PZSyOf65PW6Dvy7ebcvP

Binary file not shown.

Binary file not shown.

View File

@@ -14,7 +14,7 @@ Including another URLconf
2. Add a URL to urlpatterns: re_path('blog/', include('blog.urls'))
"""
from django.urls import re_path
from app import views, cob, email, backup, server, importdata
from app import views,hetzner, cob, email, backup, server, importdata
urlpatterns = [
@@ -46,9 +46,11 @@ urlpatterns = [
re_path('set-token-expiry/', views.set_token_expiry),
re_path('download-contract/(?P<name>.+)', views.download_contract),
re_path('execute-command/$', server.execute_command),
re_path('product/(?P<action>[\w]+)/$', hetzner.do_hetzner),
re_path('generate-document/$',views.generate_document),
re_path('model-fields/(?P<name>.+)/', importdata.model_fields),
re_path('read-excel/', importdata.read_excel),
re_path('find-key/$', importdata.find_key),
re_path('email-preview/$', views.preview_email_template)
]

Binary file not shown.

Binary file not shown.

69
app/hetzner.py Normal file
View File

@@ -0,0 +1,69 @@
# hetzner.py
from __future__ import annotations
import json
from os import environ
from dotenv import load_dotenv
from hcloud import Client
from django.http import JsonResponse
from django.views.decorators.csrf import csrf_exempt
load_dotenv()
def get_client():
return Client(token=environ["HCLOUD_TOKEN"])
# ── router ──────────────────────────────────────────────────────────────────
@csrf_exempt
def do_hetzner(request, action):
routes = {
"get_server_types": get_server_types,
}
handler = routes.get(action)
if handler is None:
return JsonResponse({"error": f"Action '{action}' not found"}, status=404)
try:
body = json.loads(request.body) if request.body else {}
except json.JSONDecodeError:
return JsonResponse({"error": "Invalid JSON body"}, status=400)
return handler(request, body)
# ── handlers ─────────────────────────────────────────────────────────────────
def get_server_types(request, body):
client = get_client()
server_types = client.server_types.get_all()
def serialize_server_type(st):
dm = st.data_model
return {
"id": dm.id,
"name": dm.name,
"description": dm.description,
"category": dm.category,
"cores": dm.cores,
"memory": dm.memory,
"disk": dm.disk,
"storage_type": dm.storage_type,
"cpu_type": dm.cpu_type,
"architecture": dm.architecture,
"deprecated": dm.deprecated,
"prices": dm.prices,
"locations": [
{
"id": loc.location.id,
"name": loc.location.name,
"deprecation": {
"announced": loc.deprecation.announced.isoformat(),
"unavailable_after": loc.deprecation.unavailable_after.isoformat(),
} if loc.deprecation else None,
}
for loc in dm.locations
],
}
result = [serialize_server_type(st) for st in server_types]
return JsonResponse(result, safe=False)

View File

@@ -0,0 +1,37 @@
# Generated by Django 5.1.7 on 2026-04-02 02:33
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('app', '0007_alter_customer_type'),
]
operations = [
migrations.CreateModel(
name='Data_Story',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('title', models.CharField(max_length=200)),
('subtitle', models.CharField(max_length=400, null=True)),
('image', models.TextField(null=True)),
('header', models.JSONField(null=True)),
('content', models.JSONField(null=True)),
('canonical', models.CharField(max_length=200, null=True)),
('tags', models.JSONField(null=True)),
('meta_desc', models.TextField(null=True)),
('create_time', models.DateTimeField(auto_now_add=True, null=True)),
('update_time', models.DateTimeField(auto_now=True, null=True)),
('category', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.category')),
('language', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.lang_choice')),
('status', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.display_status')),
('user', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.user')),
],
options={
'db_table': 'data_story',
},
),
]

View File

@@ -0,0 +1,24 @@
# Generated by Django 5.1.7 on 2026-04-02 02:36
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('app', '0008_data_story'),
]
operations = [
migrations.RemoveField(
model_name='data_story',
name='category',
),
migrations.RemoveField(
model_name='display_status',
name='en',
),
migrations.DeleteModel(
name='Category',
),
]

View File

@@ -0,0 +1,39 @@
# Generated by Django 5.1.7 on 2026-04-02 02:37
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('app', '0009_remove_data_story_category_remove_display_status_en_and_more'),
]
operations = [
migrations.CreateModel(
name='Category',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('item', models.CharField(max_length=30, unique=True)),
('value', models.CharField(max_length=100)),
('level', models.PositiveIntegerField()),
('parent', models.CharField(max_length=30, null=True)),
('index', models.PositiveIntegerField(default=0)),
('icon', models.CharField(max_length=50, null=True)),
('image', models.CharField(max_length=500, null=True)),
('link', models.CharField(max_length=500, null=True)),
('create_time', models.DateTimeField(auto_now_add=True, null=True)),
('update_time', models.DateTimeField(null=True)),
],
options={
'db_table': 'category',
},
),
migrations.AddField(
model_name='data_story',
name='category',
field=models.ForeignKey(default=1, on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.category'),
preserve_default=False,
),
]

View File

@@ -0,0 +1,35 @@
# Generated by Django 5.1.7 on 2026-04-02 07:31
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('app', '0010_category_data_story_category'),
]
operations = [
migrations.CreateModel(
name='Webadmin_Setting',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('category', models.CharField(max_length=100)),
('classify', models.CharField(max_length=100)),
('code', models.CharField(max_length=100)),
('vi', models.TextField()),
('en', models.TextField(null=True)),
('image', models.TextField(null=True)),
('icon', models.TextField(null=True)),
('link', models.TextField(null=True)),
('detail', models.JSONField(null=True)),
('detail_en', models.JSONField(null=True)),
('index', models.IntegerField(default=0, null=True)),
('create_time', models.DateTimeField(auto_now_add=True, null=True)),
],
options={
'db_table': 'webadmin_setting',
'unique_together': {('category', 'classify', 'code')},
},
),
]

View File

@@ -255,6 +255,16 @@ class Bank(models.Model):
db_table = 'bank'
class Display_Status(models.Model):
code = models.CharField(max_length=30, null=False, unique=True)
name = models.CharField(max_length=100, null=False)
index = models.IntegerField(null=True, default=1)
create_time = models.DateTimeField(null=True, auto_now_add=True)
class Meta:
db_table = 'display_status'
class User_Setting(models.Model):
name = models.CharField(max_length=200, null=False, unique=True)
detail = models.JSONField(null=False)
@@ -543,25 +553,6 @@ class Approve_Status(models.Model):
db_table = 'approve_status'
class Category(models.Model):
code = models.CharField(max_length=30, null=False, unique=True)
name = models.CharField(max_length=100, null=False)
create_time = models.DateTimeField(null=True, auto_now_add=True)
class Meta:
db_table = 'category'
class Display_Status(models.Model):
code = models.CharField(max_length=30, null=False, unique=True)
name = models.CharField(max_length=100, null=False)
en = models.CharField(max_length=100, null=True)
index = models.IntegerField(null=True, default=1)
create_time = models.DateTimeField(null=True, auto_now_add=True)
class Meta:
db_table = 'display_status'
class Payment_Status(models.Model):
code = models.CharField(max_length=30, null=False, unique=True)
@@ -861,6 +852,62 @@ class Issued_Place(models.Model):
db_table = 'issued_place'
class Category(models.Model):
item = models.CharField(max_length=30, null=False, unique = True)
value = models.CharField(max_length=100, null=False)
level = models.PositiveIntegerField(null=False)
parent = models.CharField(max_length=30, null=True)
index = models.PositiveIntegerField(null=False, default=0)
icon = models.CharField(max_length=50, null=True)
image = models.CharField(max_length=500, null=True)
link = models.CharField(max_length=500, null=True)
create_time = models.DateTimeField(null = True, auto_now_add=True)
update_time = models.DateTimeField(null = True)
class Meta:
db_table = 'category'
class Data_Story(models.Model):
title = models.CharField(max_length=200, null=False)
subtitle = models.CharField(max_length=400, null=True)
image = models.TextField(null=True)
header = models.JSONField(null=True)
content = models.JSONField(null=True)
canonical = models.CharField(max_length=200, null=True)
category = models.ForeignKey(Category, null=False, related_name='+', on_delete=models.PROTECT)
status = models.ForeignKey(Display_Status, null=False, related_name='+', on_delete=models.PROTECT)
language = models.ForeignKey(Lang_Choice, null=False, related_name='+', on_delete=models.PROTECT)
tags = models.JSONField(null=True)
meta_desc = models.TextField(null=True)
user = models.ForeignKey(User, null=False, related_name='+', on_delete=models.PROTECT)
create_time = models.DateTimeField(null=True, auto_now_add=True)
update_time = models.DateTimeField(null=True, auto_now=True)
class Meta:
db_table = 'data_story'
class Webadmin_Setting(models.Model):
category = models.CharField(max_length=100, null=False)
classify = models.CharField(max_length=100, null=False)
code = models.CharField(max_length=100, null = False)
vi = models.TextField(null=False)
en = models.TextField(null=True)
image = models.TextField(null=True)
icon = models.TextField(null=True)
link = models.TextField(null=True)
detail = models.JSONField(null=True)
detail_en = models.JSONField(null=True)
index = models.IntegerField(null=True, default=0)
create_time = models.DateTimeField(null=True, auto_now_add=True)
class Meta:
db_table = 'webadmin_setting'
unique_together = ('category', 'classify', 'code')
class Company(AutoCodeModel):
code_prefix = "CP"
code_padding = 5

View File

@@ -23,3 +23,5 @@ channels
prefect
croniter
uvicorn[standard]
hcloud
python-dotenv