Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions prisma/migrations/20260521004958_add_banners/migration.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
-- CreateTable
CREATE TABLE "Banners" (
"id_banner" SERIAL NOT NULL,
"title" VARCHAR(120) NOT NULL,

Check warning on line 4 in prisma/migrations/20260521004958_add_banners/migration.sql

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Use VARCHAR2 instead of VARCHAR.

See more on https://sonarcloud.io/project/issues?id=CrisNAC_BackendMarketplace&issues=AZ5IMmnaOoPJ8sHDDU0H&open=AZ5IMmnaOoPJ8sHDDU0H&pullRequest=165
"description" TEXT,
"image_url" VARCHAR(500) NOT NULL,

Check warning on line 6 in prisma/migrations/20260521004958_add_banners/migration.sql

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Use VARCHAR2 instead of VARCHAR.

See more on https://sonarcloud.io/project/issues?id=CrisNAC_BackendMarketplace&issues=AZ5IMmnaOoPJ8sHDDU0I&open=AZ5IMmnaOoPJ8sHDDU0I&pullRequest=165
"link_url" VARCHAR(500),

Check warning on line 7 in prisma/migrations/20260521004958_add_banners/migration.sql

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Use VARCHAR2 instead of VARCHAR.

See more on https://sonarcloud.io/project/issues?id=CrisNAC_BackendMarketplace&issues=AZ5IMmnaOoPJ8sHDDU0J&open=AZ5IMmnaOoPJ8sHDDU0J&pullRequest=165
"start_at" TIMESTAMPTZ NOT NULL,
"end_at" TIMESTAMPTZ,
"is_active" BOOLEAN NOT NULL DEFAULT true,
"status" BOOLEAN NOT NULL DEFAULT true,
"created_at" TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updated_at" TIMESTAMPTZ NOT NULL,

CONSTRAINT "Banners_pkey" PRIMARY KEY ("id_banner")
);
Comment thread
Andoumeda marked this conversation as resolved.
15 changes: 15 additions & 0 deletions prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,21 @@ model Notifications {
user Users @relation(fields: [fk_user], references: [id_user])
}

//------------------------------------BANNERS PROMOCIONALES----------------------------------------
model Banners {
id_banner Int @id @default(autoincrement())
title String @db.VarChar(120)
description String? @db.Text
image_url String @db.VarChar(500)
link_url String? @db.VarChar(500)
start_at DateTime @db.Timestamptz
end_at DateTime? @db.Timestamptz
is_active Boolean @default(true)
status Boolean @default(true)
created_at DateTime @default(now()) @db.Timestamptz
updated_at DateTime @updatedAt @db.Timestamptz
}

//------------------------------------COMERCIOS----------------------------------------
model Stores {
id_store Int @id @default(autoincrement())
Expand Down
6 changes: 6 additions & 0 deletions src/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,9 @@ import {
adminCategoryRoutes,
adminStoresRoutes,
adminProductsRoutes,
adminBannersRoutes,
} from "./modules/admin/index.js";
import { bannerRoutes } from "./modules/global/banners/banners.routes.js";

const app = express();

Expand Down Expand Up @@ -131,10 +133,14 @@ app.use("/api/admin", adminUsersRoutes);
app.use("/api/admin/categories", adminCategoryRoutes);
app.use("/api/admin/stores", adminStoresRoutes);
app.use("/api/admin/products", adminProductsRoutes);
app.use("/api/admin/banners", adminBannersRoutes);

// Rutas de distancias
app.use("/api/distances", distanceRoutes);

// Rutas de banners
app.use("/api/banners", bannerRoutes);

app.use('/products', productImageRoutes)
app.use('/users', userImageRoutes)
app.use('/stores', storeImageRoutes)
Expand Down
5 changes: 5 additions & 0 deletions src/config/swagger.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,12 @@ import {
categoryRequestSchemas,
deliverySchemas,
orderSchemas,
bannerSchemas,
// /session
sessionSchemas,
// /admin
adminCategorySchemas,
adminBannerSchemas,
} from "../docs/schemas/index.js";

const options = {
Expand Down Expand Up @@ -54,6 +56,7 @@ const options = {
{ name: "Deliveries", description: "Gestión de repartidores" },
{ name: "Images", description: "Gestión de imágenes" },
{ name: "Admin", description: "Gestión de administración" },
{ name: "Banners", description: "Banners promocionales" },
],
components: {
securitySchemes: {
Expand All @@ -77,12 +80,14 @@ const options = {
...categoryRequestSchemas,
...deliverySchemas,
...orderSchemas,
...bannerSchemas,
// /session
...sessionSchemas,
// /images
...imageSchemas,
// /admin
...adminCategorySchemas,
...adminBannerSchemas,
}
},
security: [
Expand Down
68 changes: 68 additions & 0 deletions src/docs/schemas/admin/admin-banner.schema.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
export const adminBannerSchemas = {
AdminBannerCreateBody: {
type: "object",
required: ["title", "imageUrl", "startAt"],
properties: {
title: { type: "string", minLength: 1, maxLength: 120, example: "Semana Eco" },
description: { type: "string", nullable: true, example: "Descuentos hasta 30%" },
imageUrl: { type: "string", example: "https://cdn.example.com/banners/eco.jpg" },
linkUrl: { type: "string", nullable: true, example: "https://frontend.example.com/ofertas" },
startAt: { type: "string", format: "date-time" },
endAt: { type: "string", format: "date-time", nullable: true },
isActive: { type: "boolean", example: true }
}
},
AdminBannerUpdateBody: {
type: "object",
properties: {
title: { type: "string", minLength: 1, maxLength: 120, example: "Semana Eco" },
description: { type: "string", nullable: true, example: "Descuentos hasta 30%" },
imageUrl: { type: "string", example: "https://cdn.example.com/banners/eco.jpg" },
linkUrl: { type: "string", nullable: true, example: "https://frontend.example.com/ofertas" },
startAt: { type: "string", format: "date-time" },
endAt: { type: "string", format: "date-time", nullable: true },
isActive: { type: "boolean", example: true }
}
},
AdminBannerToggleBody: {
type: "object",
required: ["isActive"],
properties: {
isActive: { type: "boolean", example: false }
}
},
AdminBannerResponse: {
type: "object",
properties: {
id: { type: "integer", example: 12 },
title: { type: "string", example: "Semana Eco" },
description: { type: "string", nullable: true, example: "Descuentos hasta 30%" },
imageUrl: { type: "string", example: "https://cdn.example.com/banners/eco.jpg" },
linkUrl: { type: "string", nullable: true, example: "https://frontend.example.com/ofertas" },
startAt: { type: "string", format: "date-time" },
endAt: { type: "string", format: "date-time", nullable: true },
isActive: { type: "boolean", example: true },
status: { type: "boolean", example: true },
createdAt: { type: "string", format: "date-time" },
updatedAt: { type: "string", format: "date-time" }
}
},
AdminBannerListResponse: {
type: "object",
properties: {
data: {
type: "array",
items: { $ref: "#/components/schemas/AdminBannerResponse" }
},
pagination: {
type: "object",
properties: {
total: { type: "integer", example: 3 },
page: { type: "integer", example: 1 },
limit: { type: "integer", example: 20 },
totalPages: { type: "integer", example: 1 }
}
}
}
}
};
20 changes: 20 additions & 0 deletions src/docs/schemas/banner.schema.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
export const bannerSchemas = {
BannerPublicResponse: {
type: "object",
properties: {
id: { type: "integer", example: 12 },
title: { type: "string", example: "Semana Eco" },
description: { type: "string", nullable: true, example: "Descuentos hasta 30%" },
imageUrl: { type: "string", example: "https://cdn.example.com/banners/eco.jpg" },
linkUrl: { type: "string", nullable: true, example: "https://frontend.example.com/ofertas" },
startAt: { type: "string", format: "date-time" },
endAt: { type: "string", format: "date-time", nullable: true },
isActive: { type: "boolean", example: true },
createdAt: { type: "string", format: "date-time" }
}
},
BannerPublicListResponse: {
type: "array",
items: { $ref: "#/components/schemas/BannerPublicResponse" }
}
};
2 changes: 2 additions & 0 deletions src/docs/schemas/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,14 @@ export * from "./commerce/category-request.schema.js";
export * from "./commerce/delivery-assignment.schema.js";
export * from "./delivery.schema.js";
export * from "./order.schema.js";
export * from "./banner.schema.js";

// Session schemas
export * from "./session/session.schema.js";

// Admin schemas
export * from "./admin/admin-category.schema.js";
export * from "./admin/admin-banner.schema.js";

// Users schemas
export * from "./users/cart.schema.js"
46 changes: 46 additions & 0 deletions src/modules/admin/banners/admin-banners.controller.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { validateId } from "../../../lib/validators.js";
import {
createAdminBannerService,
getAdminBannersService,
toggleAdminBannerActiveService,
updateAdminBannerService,
} from "./admin-banners.service.js";

export const createAdminBanner = async (req, res, next) => {
try {
const result = await createAdminBannerService(req.body);
return res.status(201).json(result);
} catch (error) {
next(error);
}
};

export const getAdminBanners = async (req, res, next) => {
try {
const { search, active, status } = req.query;
const result = await getAdminBannersService({ search, active, status }, req.pagination);
return res.status(200).json(result);
} catch (error) {
next(error);
}
};

export const updateAdminBanner = async (req, res, next) => {
try {
const id = validateId(req.params.id);
const result = await updateAdminBannerService(id, req.body);
return res.status(200).json(result);
} catch (error) {
next(error);
}
};

export const toggleAdminBannerActive = async (req, res, next) => {
try {
const id = validateId(req.params.id);
const result = await toggleAdminBannerActiveService(id, req.body?.isActive);
return res.status(200).json(result);
} catch (error) {
next(error);
}
};
Loading
Loading