chore: Новый черновик DRAFT, удалить старые docs-v

This commit is contained in:
2026-07-30 09:19:59 +03:00
parent 6f6e4896af
commit 590fb63ca7
122 changed files with 29145 additions and 3253 deletions

View File

@@ -0,0 +1,217 @@
import {
Body,
Controller,
Get,
Headers,
Param,
Patch,
Post,
Query,
Req,
Res,
UseGuards,
} from "@nestjs/common";
import {
ApiCookieAuth,
ApiCreatedResponse,
ApiNotModifiedResponse,
ApiOkResponse,
ApiOperation,
ApiSecurity,
ApiTags,
} from "@nestjs/swagger";
import type { Response } from "express";
import {
ApiDemoScenarioHeader,
ApiOrganizationHeader,
ApiStandardErrors,
} from "../../../common/api.decorators";
import {
ComplexCookieGuard,
ComplexCsrfGuard,
type ComplexDemoRequest,
ComplexOrganizationGuard,
ComplexRoles,
ComplexRolesGuard,
} from "../complex.auth";
import { ComplexStore } from "../complex.store";
import {
AdjustInventoryDto,
BrandsResponseDto,
ComplexCategoriesResponseDto,
ComplexProductResponseDto,
ComplexProductsResponseDto,
CreateComplexProductDto,
CursorProductQueryDto,
InventoryItemResponseDto,
InventoryResponseDto,
UpdateComplexProductDto,
WarehousesResponseDto,
} from "../dto/catalog.dto";
import { ComplexRole } from "../dto/identity.dto";
@ApiTags("Products")
@ApiCookieAuth("cookieSession")
@ApiOrganizationHeader()
@ApiDemoScenarioHeader()
@UseGuards(ComplexCookieGuard, ComplexOrganizationGuard)
@Controller("products")
export class ComplexProductsController {
constructor(private readonly store: ComplexStore) {}
@Get()
@ApiOperation({ summary: "List tenant products using cursor pagination" })
@ApiOkResponse({ type: ComplexProductsResponseDto })
@ApiStandardErrors({ auth: true })
list(
@Req() request: ComplexDemoRequest,
@Query() query: CursorProductQueryDto,
): ComplexProductsResponseDto {
return this.store.listProducts(request.organizationId!, query);
}
@Get(":id")
@ApiOperation({
summary: "Get a rich product with variants and ETag support",
})
@ApiOkResponse({ type: ComplexProductResponseDto })
@ApiNotModifiedResponse()
@ApiStandardErrors({ auth: true, notFound: true })
get(
@Req() request: ComplexDemoRequest,
@Param("id") id: string,
@Headers("if-none-match") ifNoneMatch: string | undefined,
@Res({ passthrough: true }) response: Response,
): ComplexProductResponseDto | undefined {
const product = this.store.getProduct(request.organizationId!, id);
const etag = `W/\"${product.id}-v${product.version}\"`;
response.setHeader("ETag", etag);
response.setHeader("Cache-Control", "private, max-age=0, must-revalidate");
if (etag === ifNoneMatch) {
response.status(304);
return undefined;
}
return { data: product };
}
@Post()
@UseGuards(ComplexRolesGuard, ComplexCsrfGuard)
@ComplexRoles(ComplexRole.Admin, ComplexRole.Manager)
@ApiSecurity("csrf")
@ApiOperation({ summary: "Create a tenant product with variants" })
@ApiCreatedResponse({ type: ComplexProductResponseDto })
@ApiStandardErrors({ auth: true })
create(
@Req() request: ComplexDemoRequest,
@Body() dto: CreateComplexProductDto,
): ComplexProductResponseDto {
return {
data: this.store.createProduct(
request.organizationId!,
request.user!.id,
dto,
),
};
}
@Patch(":id")
@UseGuards(ComplexRolesGuard, ComplexCsrfGuard)
@ComplexRoles(ComplexRole.Admin, ComplexRole.Manager)
@ApiSecurity("csrf")
@ApiOperation({ summary: "Update a product using optimistic locking" })
@ApiOkResponse({ type: ComplexProductResponseDto })
@ApiStandardErrors({ auth: true, notFound: true, conflict: true })
update(
@Req() request: ComplexDemoRequest,
@Param("id") id: string,
@Body() dto: UpdateComplexProductDto,
): ComplexProductResponseDto {
return {
data: this.store.updateProduct(
request.organizationId!,
request.user!.id,
id,
dto,
),
};
}
}
@ApiTags("Catalog")
@ApiCookieAuth("cookieSession")
@ApiOrganizationHeader()
@ApiDemoScenarioHeader()
@UseGuards(ComplexCookieGuard, ComplexOrganizationGuard)
@Controller()
export class ComplexCatalogController {
constructor(private readonly store: ComplexStore) {}
@Get("categories")
@ApiOperation({ summary: "List a recursive category tree" })
@ApiOkResponse({ type: ComplexCategoriesResponseDto })
@ApiStandardErrors({ auth: true })
categories(@Req() request: ComplexDemoRequest): ComplexCategoriesResponseDto {
return { data: this.store.listCategories(request.organizationId!) };
}
@Get("brands")
@ApiOperation({ summary: "List product brands" })
@ApiOkResponse({ type: BrandsResponseDto })
@ApiStandardErrors({ auth: true })
brands(@Req() request: ComplexDemoRequest): BrandsResponseDto {
return { data: this.store.listBrands(request.organizationId!) };
}
}
@ApiTags("Inventory")
@ApiCookieAuth("cookieSession")
@ApiOrganizationHeader()
@ApiDemoScenarioHeader()
@UseGuards(ComplexCookieGuard, ComplexOrganizationGuard)
@Controller()
export class ComplexInventoryController {
constructor(private readonly store: ComplexStore) {}
@Get("warehouses")
@ApiOperation({ summary: "List tenant warehouses" })
@ApiOkResponse({ type: WarehousesResponseDto })
@ApiStandardErrors({ auth: true })
warehouses(@Req() request: ComplexDemoRequest): WarehousesResponseDto {
return { data: this.store.listWarehouses(request.organizationId!) };
}
@Get("inventory")
@ApiOperation({ summary: "List inventory with optional product filter" })
@ApiOkResponse({ type: InventoryResponseDto })
@ApiStandardErrors({ auth: true })
inventory(
@Req() request: ComplexDemoRequest,
@Query("productId") productId?: string,
): InventoryResponseDto {
return {
data: this.store.listInventory(request.organizationId!, productId),
};
}
@Post("inventory/:id/adjust")
@UseGuards(ComplexRolesGuard, ComplexCsrfGuard)
@ComplexRoles(ComplexRole.Admin, ComplexRole.Manager)
@ApiSecurity("csrf")
@ApiOperation({ summary: "Adjust stock using optimistic locking" })
@ApiOkResponse({ type: InventoryItemResponseDto })
@ApiStandardErrors({ auth: true, notFound: true, conflict: true })
adjust(
@Req() request: ComplexDemoRequest,
@Param("id") id: string,
@Body() dto: AdjustInventoryDto,
): InventoryItemResponseDto {
return {
data: this.store.adjustInventory(
request.organizationId!,
request.user!.id,
id,
dto,
),
};
}
}