اولین نسخه بکاند آرامش پلازا
This commit is contained in:
@@ -0,0 +1,70 @@
|
||||
from fastapi import APIRouter, Depends, HTTPException, status
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from app.auth import get_current_admin
|
||||
from app.database import get_db
|
||||
from app import models, schemas
|
||||
|
||||
router = APIRouter(prefix="/api/articles", tags=["Articles"])
|
||||
|
||||
|
||||
@router.get("", response_model=list[schemas.ArticleOut])
|
||||
def list_articles(category: str | None = None, db: Session = Depends(get_db)):
|
||||
query = db.query(models.Article)
|
||||
if category:
|
||||
query = query.filter(models.Article.category == category)
|
||||
return query.order_by(models.Article.order).all()
|
||||
|
||||
|
||||
@router.get("/{slug}", response_model=schemas.ArticleOut)
|
||||
def get_article(slug: str, db: Session = Depends(get_db)):
|
||||
article = db.query(models.Article).filter(models.Article.slug == slug).first()
|
||||
if not article:
|
||||
raise HTTPException(status.HTTP_404_NOT_FOUND, "مقاله پیدا نشد")
|
||||
return article
|
||||
|
||||
|
||||
@router.post("", response_model=schemas.ArticleOut, status_code=status.HTTP_201_CREATED)
|
||||
def create_article(
|
||||
payload: schemas.ArticleCreate,
|
||||
db: Session = Depends(get_db),
|
||||
_admin=Depends(get_current_admin),
|
||||
):
|
||||
if db.query(models.Article).filter(models.Article.slug == payload.slug).first():
|
||||
raise HTTPException(status.HTTP_400_BAD_REQUEST, "این slug قبلاً استفاده شده است")
|
||||
article = models.Article(**payload.model_dump())
|
||||
db.add(article)
|
||||
db.commit()
|
||||
db.refresh(article)
|
||||
return article
|
||||
|
||||
|
||||
@router.put("/{article_id}", response_model=schemas.ArticleOut)
|
||||
def update_article(
|
||||
article_id: int,
|
||||
payload: schemas.ArticleUpdate,
|
||||
db: Session = Depends(get_db),
|
||||
_admin=Depends(get_current_admin),
|
||||
):
|
||||
article = db.get(models.Article, article_id)
|
||||
if not article:
|
||||
raise HTTPException(status.HTTP_404_NOT_FOUND, "مقاله پیدا نشد")
|
||||
for field, value in payload.model_dump(exclude_unset=True).items():
|
||||
setattr(article, field, value)
|
||||
db.commit()
|
||||
db.refresh(article)
|
||||
return article
|
||||
|
||||
|
||||
@router.delete("/{article_id}", status_code=status.HTTP_204_NO_CONTENT)
|
||||
def delete_article(
|
||||
article_id: int,
|
||||
db: Session = Depends(get_db),
|
||||
_admin=Depends(get_current_admin),
|
||||
):
|
||||
article = db.get(models.Article, article_id)
|
||||
if not article:
|
||||
raise HTTPException(status.HTTP_404_NOT_FOUND, "مقاله پیدا نشد")
|
||||
db.delete(article)
|
||||
db.commit()
|
||||
return None
|
||||
@@ -0,0 +1,25 @@
|
||||
from fastapi import APIRouter, Depends, HTTPException, status
|
||||
from fastapi.security import OAuth2PasswordRequestForm
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from app.auth import authenticate_admin, create_access_token
|
||||
from app.database import get_db
|
||||
from app.schemas import Token
|
||||
|
||||
router = APIRouter(prefix="/api/auth", tags=["Auth"])
|
||||
|
||||
|
||||
@router.post("/login", response_model=Token)
|
||||
def login(form_data: OAuth2PasswordRequestForm = Depends(), db: Session = Depends(get_db)):
|
||||
"""
|
||||
ورود ادمین. با فرم استاندارد OAuth2 (username, password) کار میکند —
|
||||
یعنی از Swagger UI (/docs) هم مستقیماً قابل تست است.
|
||||
"""
|
||||
user = authenticate_admin(db, form_data.username, form_data.password)
|
||||
if not user:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_401_UNAUTHORIZED,
|
||||
detail="نام کاربری یا رمز عبور اشتباه است",
|
||||
)
|
||||
token = create_access_token({"sub": user.username})
|
||||
return Token(access_token=token)
|
||||
@@ -0,0 +1,38 @@
|
||||
from fastapi import APIRouter, Depends
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from app.auth import get_current_admin
|
||||
from app.database import get_db
|
||||
from app import models, schemas
|
||||
|
||||
router = APIRouter(prefix="/api/brand", tags=["Brand"])
|
||||
|
||||
|
||||
def _get_or_create_brand(db: Session) -> models.Brand:
|
||||
brand = db.get(models.Brand, 1)
|
||||
if not brand:
|
||||
brand = models.Brand(id=1)
|
||||
db.add(brand)
|
||||
db.commit()
|
||||
db.refresh(brand)
|
||||
return brand
|
||||
|
||||
|
||||
@router.get("", response_model=schemas.BrandOut)
|
||||
def get_brand(db: Session = Depends(get_db)):
|
||||
"""اطلاعات کلی برند (نام، لوگو، تلفن، ایمیل، آدرس و...) — یک رکورد ثابت."""
|
||||
return _get_or_create_brand(db)
|
||||
|
||||
|
||||
@router.put("", response_model=schemas.BrandOut)
|
||||
def update_brand(
|
||||
payload: schemas.BrandUpdate,
|
||||
db: Session = Depends(get_db),
|
||||
_admin=Depends(get_current_admin),
|
||||
):
|
||||
brand = _get_or_create_brand(db)
|
||||
for field, value in payload.model_dump(exclude_unset=True).items():
|
||||
setattr(brand, field, value)
|
||||
db.commit()
|
||||
db.refresh(brand)
|
||||
return brand
|
||||
@@ -0,0 +1,59 @@
|
||||
from fastapi import APIRouter, Depends, HTTPException, status
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from app.auth import get_current_admin
|
||||
from app.database import get_db
|
||||
from app import models, schemas
|
||||
|
||||
router = APIRouter(prefix="/api/contact", tags=["Contact"])
|
||||
|
||||
|
||||
@router.post("", response_model=schemas.ContactOut, status_code=status.HTTP_201_CREATED)
|
||||
def submit_contact(payload: schemas.ContactCreate, db: Session = Depends(get_db)):
|
||||
"""این اندپوینت عمومی است — فرم تماس سایت آن را صدا میزند."""
|
||||
lead = models.ContactLead(**payload.model_dump())
|
||||
db.add(lead)
|
||||
db.commit()
|
||||
db.refresh(lead)
|
||||
return lead
|
||||
|
||||
|
||||
@router.get("", response_model=list[schemas.ContactOut])
|
||||
def list_contacts(
|
||||
db: Session = Depends(get_db),
|
||||
_admin=Depends(get_current_admin),
|
||||
):
|
||||
"""فقط ادمین: لیست همه درخواستهای تماس، جدیدترین اول."""
|
||||
return db.query(models.ContactLead).order_by(models.ContactLead.created_at.desc()).all()
|
||||
|
||||
|
||||
@router.put("/{lead_id}", response_model=schemas.ContactOut)
|
||||
def update_contact(
|
||||
lead_id: int,
|
||||
payload: schemas.ContactUpdate,
|
||||
db: Session = Depends(get_db),
|
||||
_admin=Depends(get_current_admin),
|
||||
):
|
||||
"""فقط ادمین: مثلاً علامت زدن بهعنوان خواندهشده."""
|
||||
lead = db.get(models.ContactLead, lead_id)
|
||||
if not lead:
|
||||
raise HTTPException(status.HTTP_404_NOT_FOUND, "درخواست پیدا نشد")
|
||||
for field, value in payload.model_dump(exclude_unset=True).items():
|
||||
setattr(lead, field, value)
|
||||
db.commit()
|
||||
db.refresh(lead)
|
||||
return lead
|
||||
|
||||
|
||||
@router.delete("/{lead_id}", status_code=status.HTTP_204_NO_CONTENT)
|
||||
def delete_contact(
|
||||
lead_id: int,
|
||||
db: Session = Depends(get_db),
|
||||
_admin=Depends(get_current_admin),
|
||||
):
|
||||
lead = db.get(models.ContactLead, lead_id)
|
||||
if not lead:
|
||||
raise HTTPException(status.HTTP_404_NOT_FOUND, "درخواست پیدا نشد")
|
||||
db.delete(lead)
|
||||
db.commit()
|
||||
return None
|
||||
@@ -0,0 +1,48 @@
|
||||
from fastapi import APIRouter, Depends, HTTPException, status
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from app.auth import get_current_admin
|
||||
from app.database import get_db
|
||||
from app import models, schemas
|
||||
|
||||
router = APIRouter(prefix="/api/newsletter", tags=["Newsletter"])
|
||||
|
||||
|
||||
@router.post("", response_model=schemas.NewsletterOut, status_code=status.HTTP_201_CREATED)
|
||||
def subscribe(payload: schemas.NewsletterCreate, db: Session = Depends(get_db)):
|
||||
"""اندپوینت عمومی — فرم خبرنامه سایت این را صدا میزند."""
|
||||
existing = db.query(models.NewsletterSubscriber).filter(
|
||||
models.NewsletterSubscriber.email == payload.email
|
||||
).first()
|
||||
if existing:
|
||||
raise HTTPException(status.HTTP_400_BAD_REQUEST, "این ایمیل قبلاً ثبت شده است")
|
||||
sub = models.NewsletterSubscriber(email=payload.email)
|
||||
db.add(sub)
|
||||
db.commit()
|
||||
db.refresh(sub)
|
||||
return sub
|
||||
|
||||
|
||||
@router.get("", response_model=list[schemas.NewsletterOut])
|
||||
def list_subscribers(
|
||||
db: Session = Depends(get_db),
|
||||
_admin=Depends(get_current_admin),
|
||||
):
|
||||
"""فقط ادمین: لیست همه مشترکین خبرنامه."""
|
||||
return db.query(models.NewsletterSubscriber).order_by(
|
||||
models.NewsletterSubscriber.created_at.desc()
|
||||
).all()
|
||||
|
||||
|
||||
@router.delete("/{sub_id}", status_code=status.HTTP_204_NO_CONTENT)
|
||||
def delete_subscriber(
|
||||
sub_id: int,
|
||||
db: Session = Depends(get_db),
|
||||
_admin=Depends(get_current_admin),
|
||||
):
|
||||
sub = db.get(models.NewsletterSubscriber, sub_id)
|
||||
if not sub:
|
||||
raise HTTPException(status.HTTP_404_NOT_FOUND, "مشترک پیدا نشد")
|
||||
db.delete(sub)
|
||||
db.commit()
|
||||
return None
|
||||
@@ -0,0 +1,70 @@
|
||||
from fastapi import APIRouter, Depends, HTTPException, status
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from app.auth import get_current_admin
|
||||
from app.database import get_db
|
||||
from app import models, schemas
|
||||
|
||||
router = APIRouter(prefix="/api/projects", tags=["Projects"])
|
||||
|
||||
|
||||
@router.get("", response_model=list[schemas.ProjectOut])
|
||||
def list_projects(status_filter: str | None = None, db: Session = Depends(get_db)):
|
||||
query = db.query(models.Project)
|
||||
if status_filter:
|
||||
query = query.filter(models.Project.status == status_filter)
|
||||
return query.order_by(models.Project.order).all()
|
||||
|
||||
|
||||
@router.get("/{slug}", response_model=schemas.ProjectOut)
|
||||
def get_project(slug: str, db: Session = Depends(get_db)):
|
||||
project = db.query(models.Project).filter(models.Project.slug == slug).first()
|
||||
if not project:
|
||||
raise HTTPException(status.HTTP_404_NOT_FOUND, "پروژه پیدا نشد")
|
||||
return project
|
||||
|
||||
|
||||
@router.post("", response_model=schemas.ProjectOut, status_code=status.HTTP_201_CREATED)
|
||||
def create_project(
|
||||
payload: schemas.ProjectCreate,
|
||||
db: Session = Depends(get_db),
|
||||
_admin=Depends(get_current_admin),
|
||||
):
|
||||
if db.query(models.Project).filter(models.Project.slug == payload.slug).first():
|
||||
raise HTTPException(status.HTTP_400_BAD_REQUEST, "این slug قبلاً استفاده شده است")
|
||||
project = models.Project(**payload.model_dump())
|
||||
db.add(project)
|
||||
db.commit()
|
||||
db.refresh(project)
|
||||
return project
|
||||
|
||||
|
||||
@router.put("/{project_id}", response_model=schemas.ProjectOut)
|
||||
def update_project(
|
||||
project_id: int,
|
||||
payload: schemas.ProjectUpdate,
|
||||
db: Session = Depends(get_db),
|
||||
_admin=Depends(get_current_admin),
|
||||
):
|
||||
project = db.get(models.Project, project_id)
|
||||
if not project:
|
||||
raise HTTPException(status.HTTP_404_NOT_FOUND, "پروژه پیدا نشد")
|
||||
for field, value in payload.model_dump(exclude_unset=True).items():
|
||||
setattr(project, field, value)
|
||||
db.commit()
|
||||
db.refresh(project)
|
||||
return project
|
||||
|
||||
|
||||
@router.delete("/{project_id}", status_code=status.HTTP_204_NO_CONTENT)
|
||||
def delete_project(
|
||||
project_id: int,
|
||||
db: Session = Depends(get_db),
|
||||
_admin=Depends(get_current_admin),
|
||||
):
|
||||
project = db.get(models.Project, project_id)
|
||||
if not project:
|
||||
raise HTTPException(status.HTTP_404_NOT_FOUND, "پروژه پیدا نشد")
|
||||
db.delete(project)
|
||||
db.commit()
|
||||
return None
|
||||
@@ -0,0 +1,65 @@
|
||||
from app.crud_router import build_crud_router
|
||||
from app import models, schemas
|
||||
|
||||
services_router = build_crud_router(
|
||||
prefix="/api/services",
|
||||
tag="Services",
|
||||
model=models.Service,
|
||||
create_schema=schemas.ServiceCreate,
|
||||
update_schema=schemas.ServiceUpdate,
|
||||
out_schema=schemas.ServiceOut,
|
||||
)
|
||||
|
||||
stats_router = build_crud_router(
|
||||
prefix="/api/stats",
|
||||
tag="Stats",
|
||||
model=models.Stat,
|
||||
create_schema=schemas.StatCreate,
|
||||
update_schema=schemas.StatUpdate,
|
||||
out_schema=schemas.StatOut,
|
||||
)
|
||||
|
||||
timeline_router = build_crud_router(
|
||||
prefix="/api/timeline",
|
||||
tag="Timeline",
|
||||
model=models.TimelineItem,
|
||||
create_schema=schemas.TimelineCreate,
|
||||
update_schema=schemas.TimelineUpdate,
|
||||
out_schema=schemas.TimelineOut,
|
||||
)
|
||||
|
||||
why_us_router = build_crud_router(
|
||||
prefix="/api/why-us",
|
||||
tag="WhyUs",
|
||||
model=models.WhyUsItem,
|
||||
create_schema=schemas.WhyUsCreate,
|
||||
update_schema=schemas.WhyUsUpdate,
|
||||
out_schema=schemas.WhyUsOut,
|
||||
)
|
||||
|
||||
testimonials_router = build_crud_router(
|
||||
prefix="/api/testimonials",
|
||||
tag="Testimonials",
|
||||
model=models.Testimonial,
|
||||
create_schema=schemas.TestimonialCreate,
|
||||
update_schema=schemas.TestimonialUpdate,
|
||||
out_schema=schemas.TestimonialOut,
|
||||
)
|
||||
|
||||
team_router = build_crud_router(
|
||||
prefix="/api/team",
|
||||
tag="Team",
|
||||
model=models.TeamMember,
|
||||
create_schema=schemas.TeamMemberCreate,
|
||||
update_schema=schemas.TeamMemberUpdate,
|
||||
out_schema=schemas.TeamMemberOut,
|
||||
)
|
||||
|
||||
faqs_router = build_crud_router(
|
||||
prefix="/api/faqs",
|
||||
tag="FAQs",
|
||||
model=models.Faq,
|
||||
create_schema=schemas.FaqCreate,
|
||||
update_schema=schemas.FaqUpdate,
|
||||
out_schema=schemas.FaqOut,
|
||||
)
|
||||
Reference in New Issue
Block a user