feat: add generated code

This commit is contained in:
aid-orchestrator
2026-05-12 09:31:32 +00:00
parent 62b4b052a3
commit 12179f2160
51 changed files with 1143 additions and 0 deletions

View File

@@ -0,0 +1,78 @@
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
generator client {
provider = "prisma-client-js"
}
enum MovementKind {
Receipt
Issue
Transfer
Adjustment
}
model ProductType {
id String @id @default(uuid())
name String @unique
products Product[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@map("product_types")
}
model Product {
id String @id @default(uuid())
name String
productType ProductType @relation(fields: [productTypeId], references: [id])
productTypeId String
parent Product? @relation("ProductHierarchy", fields: [parentId], references: [id])
parentId String?
children Product[] @relation("ProductHierarchy")
stockStatus StockStatus?
lines StockMovementLine[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@map("products")
}
model StockStatus {
product Product @relation(fields: [productId], references: [id])
productId String @id @unique
quantity Decimal @default(0)
inStock Boolean @default(false)
updatedAt DateTime @default(now()) @updatedAt
@@map("stock_statuses")
}
model StockMovement {
id String @id @default(uuid())
documentDate DateTime @db.Date
kind MovementKind
lines StockMovementLine[]
comment String?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@map("stock_movements")
}
model StockMovementLine {
id String @id @default(uuid())
product Product @relation(fields: [productId], references: [id])
productId String
quantity Decimal
inStock Boolean
movement StockMovement @relation(fields: [movementId], references: [id])
movementId String
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@unique([movementId, productId])
@@map("stock_movement_lines")
}

19
backend/src/app.module.ts Normal file
View File

@@ -0,0 +1,19 @@
import { Module } from '@nestjs/common';
import { AuthModule } from './auth/auth.module';
import { PrismaService } from './prisma/prisma.service';
import { ProductTypeModule } from './product-type/product-type.module';
import { ProductModule } from './product/product.module';
import { StockStatusModule } from './stock-status/stock-status.module';
import { StockMovementModule } from './stock-movement/stock-movement.module';
@Module({
imports: [
AuthModule,
ProductTypeModule,
ProductModule,
StockStatusModule,
StockMovementModule,
],
providers: [PrismaService],
})
export class AppModule {}

View File

@@ -0,0 +1,9 @@
import { IsString, IsNotEmpty } from 'class-validator';
import { ApiProperty } from '@nestjs/swagger';
export class CreateProductTypeDto {
@ApiProperty({ description: 'Наименование типа товара' })
@IsString()
@IsNotEmpty()
name: string;
}

View File

@@ -0,0 +1,4 @@
import { PartialType } from '@nestjs/mapped-types';
import { CreateProductTypeDto } from './create-product-type.dto';
export class UpdateProductTypeDto extends PartialType(CreateProductTypeDto) {}

View File

@@ -0,0 +1,54 @@
import { Controller, Get, Post, Body, Patch, Param, Delete, Query, UseGuards } from '@nestjs/common';
import { ApiBearerAuth, ApiTags } from '@nestjs/swagger';
import { ProductTypeService } from './product-type.service';
import { CreateProductTypeDto } from './dto/create-product-type.dto';
import { UpdateProductTypeDto } from './dto/update-product-type.dto';
import { JwtAuthGuard } from '../auth/jwt-auth.guard';
const parseJson = <T>(value?: string): T | undefined => {
if (!value) return undefined;
try { return JSON.parse(value) as T; } catch { return undefined; }
};
@ApiTags('product-type')
@ApiBearerAuth()
@UseGuards(JwtAuthGuard)
@Controller('product-types')
export class ProductTypeController {
constructor(private readonly productTypeService: ProductTypeService) {}
@Get()
findAll(
@Query('skip') skip?: string,
@Query('take') take?: string,
@Query('orderBy') orderBy?: string,
@Query('where') where?: string,
) {
return this.productTypeService.findAll({
skip: skip ? Number(skip) : 0,
take: take ? Number(take) : 25,
orderBy: parseJson(orderBy),
where: parseJson(where),
});
}
@Get(':id')
findOne(@Param('id') id: string) {
return this.productTypeService.findOne({ id });
}
@Post()
create(@Body() dto: CreateProductTypeDto) {
return this.productTypeService.create(dto);
}
@Patch(':id')
update(@Param('id') id: string, @Body() dto: UpdateProductTypeDto) {
return this.productTypeService.update({ where: { id }, data: dto });
}
@Delete(':id')
remove(@Param('id') id: string) {
return this.productTypeService.remove({ id });
}
}

View File

@@ -0,0 +1,10 @@
import { Module } from '@nestjs/common';
import { ProductTypeService } from './product-type.service';
import { ProductTypeController } from './product-type.controller';
import { PrismaService } from '../prisma/prisma.service';
@Module({
controllers: [ProductTypeController],
providers: [ProductTypeService, PrismaService],
})
export class ProductTypeModule {}

View File

@@ -0,0 +1,41 @@
import { Injectable } from '@nestjs/common';
import { PrismaService } from '../prisma/prisma.service';
import { ProductType, Prisma } from '@prisma/client';
@Injectable()
export class ProductTypeService {
constructor(private prisma: PrismaService) {}
async findAll(params: {
skip?: number;
take?: number;
where?: Prisma.ProductTypeWhereInput;
orderBy?: Prisma.ProductTypeOrderByWithRelationInput;
}): Promise<{ data: ProductType[]; total: number }> {
const { skip, take, where, orderBy } = params;
const [data, total] = await this.prisma.$transaction([
this.prisma.productType.findMany({ skip, take, where, orderBy }),
this.prisma.productType.count({ where }),
]);
return { data, total };
}
async findOne(where: Prisma.ProductTypeWhereUniqueInput): Promise<ProductType | null> {
return this.prisma.productType.findUnique({ where });
}
async create(data: Prisma.ProductTypeCreateInput): Promise<ProductType> {
return this.prisma.productType.create({ data });
}
async update(params: {
where: Prisma.ProductTypeWhereUniqueInput;
data: Prisma.ProductTypeUpdateInput;
}): Promise<ProductType> {
return this.prisma.productType.update(params);
}
async remove(where: Prisma.ProductTypeWhereUniqueInput): Promise<ProductType> {
return this.prisma.productType.delete({ where });
}
}

View File

@@ -0,0 +1,19 @@
import { IsString, IsNotEmpty, IsOptional } from 'class-validator';
import { ApiProperty } from '@nestjs/swagger';
export class CreateProductDto {
@ApiProperty({ description: 'Наименование товара' })
@IsString()
@IsNotEmpty()
name: string;
@ApiProperty({ description: 'ID типа товара' })
@IsString()
@IsNotEmpty()
productTypeId: string;
@ApiProperty({ description: 'ID родительского товара (для иерархии)', required: false })
@IsString()
@IsOptional()
parentId?: string;
}

View File

@@ -0,0 +1,4 @@
import { PartialType } from '@nestjs/mapped-types';
import { CreateProductDto } from './create-product.dto';
export class UpdateProductDto extends PartialType(CreateProductDto) {}

View File

@@ -0,0 +1,54 @@
import { Controller, Get, Post, Body, Patch, Param, Delete, Query, UseGuards } from '@nestjs/common';
import { ApiBearerAuth, ApiTags } from '@nestjs/swagger';
import { ProductService } from './product.service';
import { CreateProductDto } from './dto/create-product.dto';
import { UpdateProductDto } from './dto/update-product.dto';
import { JwtAuthGuard } from '../auth/jwt-auth.guard';
const parseJson = <T>(value?: string): T | undefined => {
if (!value) return undefined;
try { return JSON.parse(value) as T; } catch { return undefined; }
};
@ApiTags('product')
@ApiBearerAuth()
@UseGuards(JwtAuthGuard)
@Controller('products')
export class ProductController {
constructor(private readonly productService: ProductService) {}
@Get()
findAll(
@Query('skip') skip?: string,
@Query('take') take?: string,
@Query('orderBy') orderBy?: string,
@Query('where') where?: string,
) {
return this.productService.findAll({
skip: skip ? Number(skip) : 0,
take: take ? Number(take) : 25,
orderBy: parseJson(orderBy),
where: parseJson(where),
});
}
@Get(':id')
findOne(@Param('id') id: string) {
return this.productService.findOne({ id });
}
@Post()
create(@Body() dto: CreateProductDto) {
return this.productService.create(dto);
}
@Patch(':id')
update(@Param('id') id: string, @Body() dto: UpdateProductDto) {
return this.productService.update({ where: { id }, data: dto });
}
@Delete(':id')
remove(@Param('id') id: string) {
return this.productService.remove({ id });
}
}

View File

@@ -0,0 +1,10 @@
import { Module } from '@nestjs/common';
import { ProductService } from './product.service';
import { ProductController } from './product.controller';
import { PrismaService } from '../prisma/prisma.service';
@Module({
controllers: [ProductController],
providers: [ProductService, PrismaService],
})
export class ProductModule {}

View File

@@ -0,0 +1,74 @@
import { Injectable } from '@nestjs/common';
import { PrismaService } from '../prisma/prisma.service';
import { Product, Prisma } from '@prisma/client';
@Injectable()
export class ProductService {
constructor(private prisma: PrismaService) {}
async findAll(params: {
skip?: number;
take?: number;
where?: Prisma.ProductWhereInput;
orderBy?: Prisma.ProductOrderByWithRelationInput;
}): Promise<{ data: Product[]; total: number }> {
const { skip, take, where, orderBy } = params;
const [data, total] = await this.prisma.$transaction([
this.prisma.product.findMany({
skip,
take,
where,
orderBy,
include: {
productType: true,
parent: true,
},
}),
this.prisma.product.count({ where }),
]);
return { data, total };
}
async findOne(where: Prisma.ProductWhereUniqueInput): Promise<Product | null> {
return this.prisma.product.findUnique({
where,
include: {
productType: true,
parent: true,
},
});
}
async create(data: Prisma.ProductCreateInput): Promise<Product> {
return this.prisma.product.create({
data,
include: {
productType: true,
parent: true,
},
});
}
async update(params: {
where: Prisma.ProductWhereUniqueInput;
data: Prisma.ProductUpdateInput;
}): Promise<Product> {
return this.prisma.product.update({
...params,
include: {
productType: true,
parent: true,
},
});
}
async remove(where: Prisma.ProductWhereUniqueInput): Promise<Product> {
return this.prisma.product.delete({
where,
include: {
productType: true,
parent: true,
},
});
}
}

View File

@@ -0,0 +1,19 @@
import { IsString, IsNotEmpty, IsNumber, IsBoolean } from 'class-validator';
import { Type } from 'class-transformer';
import { ApiProperty } from '@nestjs/swagger';
export class CreateStockMovementLineDto {
@ApiProperty({ description: 'ID товара' })
@IsString()
@IsNotEmpty()
productId: string;
@ApiProperty({ description: 'Количество' })
@IsNumber()
@Type(() => Number)
quantity: number;
@ApiProperty({ description: 'Новый признак наличия после проведения' })
@IsBoolean()
inStock: boolean;
}

View File

@@ -0,0 +1,25 @@
import { IsString, IsNotEmpty, IsEnum, IsArray, IsOptional } from 'class-validator';
import { Type } from 'class-transformer';
import { ApiProperty } from '@nestjs/swagger';
import { MovementKind } from '@prisma/client';
import { CreateStockMovementLineDto } from './create-stock-movement-line.dto';
export class CreateStockMovementDto {
@ApiProperty({ description: 'Дата документа' })
@Type(() => Date)
documentDate: Date;
@ApiProperty({ enum: MovementKind, enumName: 'MovementKind', description: 'Вид движения' })
@IsEnum(MovementKind)
kind: MovementKind;
@ApiProperty({ type: [CreateStockMovementLineDto], description: 'Строки документа' })
@IsArray()
@Type(() => CreateStockMovementLineDto)
lines: CreateStockMovementLineDto[];
@ApiProperty({ description: 'Комментарий к документу', required: false })
@IsString()
@IsOptional()
comment?: string;
}

View File

@@ -0,0 +1,4 @@
import { PartialType } from '@nestjs/mapped-types';
import { CreateStockMovementLineDto } from './create-stock-movement-line.dto';
export class UpdateStockMovementLineDto extends PartialType(CreateStockMovementLineDto) {}

View File

@@ -0,0 +1,4 @@
import { PartialType } from '@nestjs/mapped-types';
import { CreateStockMovementDto } from './create-stock-movement.dto';
export class UpdateStockMovementDto extends PartialType(CreateStockMovementDto) {}

View File

@@ -0,0 +1,54 @@
import { Controller, Get, Post, Body, Patch, Param, Delete, Query, UseGuards } from '@nestjs/common';
import { ApiBearerAuth, ApiTags } from '@nestjs/swagger';
import { StockMovementService } from './stock-movement.service';
import { CreateStockMovementDto } from './dto/create-stock-movement.dto';
import { UpdateStockMovementDto } from './dto/update-stock-movement.dto';
import { JwtAuthGuard } from '../auth/jwt-auth.guard';
const parseJson = <T>(value?: string): T | undefined => {
if (!value) return undefined;
try { return JSON.parse(value) as T; } catch { return undefined; }
};
@ApiTags('stock-movement')
@ApiBearerAuth()
@UseGuards(JwtAuthGuard)
@Controller('stock-movements')
export class StockMovementController {
constructor(private readonly stockMovementService: StockMovementService) {}
@Get()
findAll(
@Query('skip') skip?: string,
@Query('take') take?: string,
@Query('orderBy') orderBy?: string,
@Query('where') where?: string,
) {
return this.stockMovementService.findAll({
skip: skip ? Number(skip) : 0,
take: take ? Number(take) : 25,
orderBy: parseJson(orderBy),
where: parseJson(where),
});
}
@Get(':id')
findOne(@Param('id') id: string) {
return this.stockMovementService.findOne({ id });
}
@Post()
create(@Body() dto: CreateStockMovementDto) {
return this.stockMovementService.create(dto);
}
@Patch(':id')
update(@Param('id') id: string, @Body() dto: UpdateStockMovementDto) {
return this.stockMovementService.update({ where: { id }, data: dto });
}
@Delete(':id')
remove(@Param('id') id: string) {
return this.stockMovementService.remove({ id });
}
}

View File

@@ -0,0 +1,10 @@
import { Module } from '@nestjs/common';
import { StockMovementService } from './stock-movement.service';
import { StockMovementController } from './stock-movement.controller';
import { PrismaService } from '../prisma/prisma.service';
@Module({
controllers: [StockMovementController],
providers: [StockMovementService, PrismaService],
})
export class StockMovementModule {}

View File

@@ -0,0 +1,89 @@
import { Injectable } from '@nestjs/common';
import { PrismaService } from '../prisma/prisma.service';
import { StockMovement, Prisma } from '@prisma/client';
@Injectable()
export class StockMovementService {
constructor(private prisma: PrismaService) {}
async findAll(params: {
skip?: number;
take?: number;
where?: Prisma.StockMovementWhereInput;
orderBy?: Prisma.StockMovementOrderByWithRelationInput;
}): Promise<{ data: StockMovement[]; total: number }> {
const { skip, take, where, orderBy } = params;
const [data, total] = await this.prisma.$transaction([
this.prisma.stockMovement.findMany({
skip,
take,
where,
orderBy,
include: {
lines: {
include: {
product: true,
},
},
},
}),
this.prisma.stockMovement.count({ where }),
]);
return { data, total };
}
async findOne(where: Prisma.StockMovementWhereUniqueInput): Promise<StockMovement | null> {
return this.prisma.stockMovement.findUnique({
where,
include: {
lines: {
include: {
product: true,
},
},
},
});
}
async create(data: Prisma.StockMovementCreateInput): Promise<StockMovement> {
return this.prisma.stockMovement.create({
data,
include: {
lines: {
include: {
product: true,
},
},
},
});
}
async update(params: {
where: Prisma.StockMovementWhereUniqueInput;
data: Prisma.StockMovementUpdateInput;
}): Promise<StockMovement> {
return this.prisma.stockMovement.update({
...params,
include: {
lines: {
include: {
product: true,
},
},
},
});
}
async remove(where: Prisma.StockMovementWhereUniqueInput): Promise<StockMovement> {
return this.prisma.stockMovement.delete({
where,
include: {
lines: {
include: {
product: true,
},
},
},
});
}
}

View File

@@ -0,0 +1,25 @@
import { IsString, IsNotEmpty, IsNumber, IsBoolean, IsOptional } from 'class-validator';
import { Type } from 'class-transformer';
import { ApiProperty } from '@nestjs/swagger';
export class CreateStockStatusDto {
@ApiProperty({ description: 'ID товара' })
@IsString()
@IsNotEmpty()
productId: string;
@ApiProperty({ description: 'Текущее количество на складе', required: false })
@IsNumber()
@IsOptional()
@Type(() => Number)
quantity?: number;
@ApiProperty({ description: 'Признак наличия товара', required: false })
@IsBoolean()
@IsOptional()
inStock?: boolean;
@ApiProperty({ description: 'Дата последнего обновления', required: false })
@IsOptional()
updatedAt?: Date;
}

View File

@@ -0,0 +1,4 @@
import { PartialType } from '@nestjs/mapped-types';
import { CreateStockStatusDto } from './create-stock-status.dto';
export class UpdateStockStatusDto extends PartialType(CreateStockStatusDto) {}

View File

@@ -0,0 +1,54 @@
import { Controller, Get, Post, Body, Patch, Param, Delete, Query, UseGuards } from '@nestjs/common';
import { ApiBearerAuth, ApiTags } from '@nestjs/swagger';
import { StockStatusService } from './stock-status.service';
import { CreateStockStatusDto } from './dto/create-stock-status.dto';
import { UpdateStockStatusDto } from './dto/update-stock-status.dto';
import { JwtAuthGuard } from '../auth/jwt-auth.guard';
const parseJson = <T>(value?: string): T | undefined => {
if (!value) return undefined;
try { return JSON.parse(value) as T; } catch { return undefined; }
};
@ApiTags('stock-status')
@ApiBearerAuth()
@UseGuards(JwtAuthGuard)
@Controller('stock-statuses')
export class StockStatusController {
constructor(private readonly stockStatusService: StockStatusService) {}
@Get()
findAll(
@Query('skip') skip?: string,
@Query('take') take?: string,
@Query('orderBy') orderBy?: string,
@Query('where') where?: string,
) {
return this.stockStatusService.findAll({
skip: skip ? Number(skip) : 0,
take: take ? Number(take) : 25,
orderBy: parseJson(orderBy),
where: parseJson(where),
});
}
@Get(':productId')
findOne(@Param('productId') productId: string) {
return this.stockStatusService.findOne({ productId });
}
@Post()
create(@Body() dto: CreateStockStatusDto) {
return this.stockStatusService.create(dto);
}
@Patch(':productId')
update(@Param('productId') productId: string, @Body() dto: UpdateStockStatusDto) {
return this.stockStatusService.update({ where: { productId }, data: dto });
}
@Delete(':productId')
remove(@Param('productId') productId: string) {
return this.stockStatusService.remove({ productId });
}
}

View File

@@ -0,0 +1,10 @@
import { Module } from '@nestjs/common';
import { StockStatusService } from './stock-status.service';
import { StockStatusController } from './stock-status.controller';
import { PrismaService } from '../prisma/prisma.service';
@Module({
controllers: [StockStatusController],
providers: [StockStatusService, PrismaService],
})
export class StockStatusModule {}

View File

@@ -0,0 +1,69 @@
import { Injectable } from '@nestjs/common';
import { PrismaService } from '../prisma/prisma.service';
import { StockStatus, Prisma } from '@prisma/client';
@Injectable()
export class StockStatusService {
constructor(private prisma: PrismaService) {}
async findAll(params: {
skip?: number;
take?: number;
where?: Prisma.StockStatusWhereInput;
orderBy?: Prisma.StockStatusOrderByWithRelationInput;
}): Promise<{ data: StockStatus[]; total: number }> {
const { skip, take, where, orderBy } = params;
const [data, total] = await this.prisma.$transaction([
this.prisma.stockStatus.findMany({
skip,
take,
where,
orderBy,
include: {
product: true,
},
}),
this.prisma.stockStatus.count({ where }),
]);
return { data, total };
}
async findOne(where: Prisma.StockStatusWhereUniqueInput): Promise<StockStatus | null> {
return this.prisma.stockStatus.findUnique({
where,
include: {
product: true,
},
});
}
async create(data: Prisma.StockStatusCreateInput): Promise<StockStatus> {
return this.prisma.stockStatus.create({
data,
include: {
product: true,
},
});
}
async update(params: {
where: Prisma.StockStatusWhereUniqueInput;
data: Prisma.StockStatusUpdateInput;
}): Promise<StockStatus> {
return this.prisma.stockStatus.update({
...params,
include: {
product: true,
},
});
}
async remove(where: Prisma.StockStatusWhereUniqueInput): Promise<StockStatus> {
return this.prisma.stockStatus.delete({
where,
include: {
product: true,
},
});
}
}

60
frontend/src/App.tsx Normal file
View File

@@ -0,0 +1,60 @@
import { Admin, Resource } from 'react-admin';
import { dataProvider } from './dataProvider';
import { authProvider } from './authProvider';
// ProductType resources
import { ProductTypeList, ProductTypeCreate, ProductTypeEdit, ProductTypeShow } from './resources/product-type';
// Product resources
import { ProductList, ProductCreate, ProductEdit, ProductShow } from './resources/product';
// StockStatus resources
import { StockStatusList, StockStatusCreate, StockStatusEdit, StockStatusShow } from './resources/stock-status';
// StockMovement resources
import { StockMovementList, StockMovementCreate, StockMovementEdit, StockMovementShow } from './resources/stock-movement';
// StockMovementLine resources
import { StockMovementLineList, StockMovementLineCreate, StockMovementLineEdit, StockMovementLineShow } from './resources/stock-movement-line';
const App = () => (
<Admin dataProvider={dataProvider} authProvider={authProvider}>
<Resource
name="product-types"
list={ProductTypeList}
create={ProductTypeCreate}
edit={ProductTypeEdit}
show={ProductTypeShow}
/>
<Resource
name="products"
list={ProductList}
create={ProductCreate}
edit={ProductEdit}
show={ProductShow}
/>
<Resource
name="stock-statuses"
list={StockStatusList}
create={StockStatusCreate}
edit={StockStatusEdit}
show={StockStatusShow}
/>
<Resource
name="stock-movements"
list={StockMovementList}
create={StockMovementCreate}
edit={StockMovementEdit}
show={StockMovementShow}
/>
<Resource
name="stock-movement-lines"
list={StockMovementLineList}
create={StockMovementLineCreate}
edit={StockMovementLineEdit}
show={StockMovementLineShow}
/>
</Admin>
);
export default App;

15
frontend/src/main.tsx Normal file
View File

@@ -0,0 +1,15 @@
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
import { initKeycloak } from './authProvider';
// Initialize Keycloak before rendering the app
initKeycloak().then(() => {
ReactDOM.createRoot(document.getElementById('root')!).render(
<React.StrictMode>
<App />
</React.StrictMode>
);
}).catch((error) => {
console.error('Failed to initialize Keycloak:', error);
});

View File

@@ -0,0 +1,9 @@
import { Create, SimpleForm, TextInput } from 'react-admin';
export const ProductTypeCreate = () => (
<Create>
<SimpleForm>
<TextInput source="name" />
</SimpleForm>
</Create>
);

View File

@@ -0,0 +1,10 @@
import { Edit, SimpleForm, TextInput } from 'react-admin';
export const ProductTypeEdit = () => (
<Edit>
<SimpleForm>
<TextInput disabled source="id" />
<TextInput source="name" />
</SimpleForm>
</Edit>
);

View File

@@ -0,0 +1,13 @@
import { List, DataTable, TextField, DateField, EditButton } from 'react-admin';
export const ProductTypeList = () => (
<List>
<DataTable>
<DataTable.Col source="id" />
<DataTable.Col source="name" />
<DataTable.Col source="createdAt" field={DateField} />
<DataTable.Col source="updatedAt" field={DateField} />
<DataTable.Col><EditButton /></DataTable.Col>
</DataTable>
</List>
);

View File

@@ -0,0 +1,12 @@
import { Show, SimpleShowLayout, TextField, DateField } from 'react-admin';
export const ProductTypeShow = () => (
<Show>
<SimpleShowLayout>
<TextField source="id" />
<TextField source="name" />
<DateField source="createdAt" />
<DateField source="updatedAt" />
</SimpleShowLayout>
</Show>
);

View File

@@ -0,0 +1,4 @@
export { ProductTypeList } from './ProductTypeList';
export { ProductTypeEdit } from './ProductTypeEdit';
export { ProductTypeCreate } from './ProductTypeCreate';
export { ProductTypeShow } from './ProductTypeShow';

View File

@@ -0,0 +1,15 @@
import { Create, SimpleForm, TextInput, ReferenceInput, SelectInput } from 'react-admin';
export const ProductCreate = () => (
<Create>
<SimpleForm>
<TextInput source="name" />
<ReferenceInput source="productTypeId" reference="product-types">
<SelectInput optionText="name" />
</ReferenceInput>
<ReferenceInput source="parentId" reference="products">
<SelectInput optionText="name" />
</ReferenceInput>
</SimpleForm>
</Create>
);

View File

@@ -0,0 +1,16 @@
import { Edit, SimpleForm, TextInput, ReferenceInput, SelectInput } from 'react-admin';
export const ProductEdit = () => (
<Edit>
<SimpleForm>
<TextInput disabled source="id" />
<TextInput source="name" />
<ReferenceInput source="productTypeId" reference="product-types">
<SelectInput optionText="name" />
</ReferenceInput>
<ReferenceInput source="parentId" reference="products">
<SelectInput optionText="name" />
</ReferenceInput>
</SimpleForm>
</Edit>
);

View File

@@ -0,0 +1,19 @@
import { List, DataTable, TextField, ReferenceField, DateField, EditButton } from 'react-admin';
export const ProductList = () => (
<List>
<DataTable>
<DataTable.Col source="id" />
<DataTable.Col source="name" />
<DataTable.Col source="productTypeId" field={ReferenceField} reference="product-types">
<TextField source="name" />
</DataTable.Col>
<DataTable.Col source="parentId" field={ReferenceField} reference="products">
<TextField source="name" />
</DataTable.Col>
<DataTable.Col source="createdAt" field={DateField} />
<DataTable.Col source="updatedAt" field={DateField} />
<DataTable.Col><EditButton /></DataTable.Col>
</DataTable>
</List>
);

View File

@@ -0,0 +1,18 @@
import { Show, SimpleShowLayout, TextField, ReferenceField, DateField } from 'react-admin';
export const ProductShow = () => (
<Show>
<SimpleShowLayout>
<TextField source="id" />
<TextField source="name" />
<ReferenceField source="productTypeId" reference="product-types">
<TextField source="name" />
</ReferenceField>
<ReferenceField source="parentId" reference="products">
<TextField source="name" />
</ReferenceField>
<DateField source="createdAt" />
<DateField source="updatedAt" />
</SimpleShowLayout>
</Show>
);

View File

@@ -0,0 +1,4 @@
export { ProductList } from './ProductList';
export { ProductEdit } from './ProductEdit';
export { ProductCreate } from './ProductCreate';
export { ProductShow } from './ProductShow';

View File

@@ -0,0 +1,16 @@
import { Create, SimpleForm, ReferenceInput, SelectInput, NumberInput, BooleanInput } from 'react-admin';
export const StockMovementLineCreate = () => (
<Create>
<SimpleForm>
<ReferenceInput source="productId" reference="products">
<SelectInput optionText="name" />
</ReferenceInput>
<ReferenceInput source="movementId" reference="stock-movements">
<SelectInput optionText="id" />
</ReferenceInput>
<NumberInput source="quantity" />
<BooleanInput source="inStock" />
</SimpleForm>
</Create>
);

View File

@@ -0,0 +1,17 @@
import { Edit, SimpleForm, TextInput, ReferenceInput, SelectInput, NumberInput, BooleanInput } from 'react-admin';
export const StockMovementLineEdit = () => (
<Edit>
<SimpleForm>
<TextInput disabled source="id" />
<ReferenceInput source="productId" reference="products">
<SelectInput optionText="name" />
</ReferenceInput>
<ReferenceInput source="movementId" reference="stock-movements">
<SelectInput optionText="id" />
</ReferenceInput>
<NumberInput source="quantity" />
<BooleanInput source="inStock" />
</SimpleForm>
</Edit>
);

View File

@@ -0,0 +1,20 @@
import { List, DataTable, TextField, ReferenceField, NumberField, BooleanField, DateField, EditButton } from 'react-admin';
export const StockMovementLineList = () => (
<List>
<DataTable>
<DataTable.Col source="id" />
<DataTable.Col source="productId" field={ReferenceField} reference="products">
<TextField source="name" />
</DataTable.Col>
<DataTable.Col source="movementId" field={ReferenceField} reference="stock-movements">
<TextField source="id" />
</DataTable.Col>
<DataTable.Col source="quantity" field={NumberField} />
<DataTable.Col source="inStock" field={BooleanField} />
<DataTable.Col source="createdAt" field={DateField} />
<DataTable.Col source="updatedAt" field={DateField} />
<DataTable.Col><EditButton /></DataTable.Col>
</DataTable>
</List>
);

View File

@@ -0,0 +1,19 @@
import { Show, SimpleShowLayout, TextField, ReferenceField, NumberField, BooleanField, DateField } from 'react-admin';
export const StockMovementLineShow = () => (
<Show>
<SimpleShowLayout>
<TextField source="id" />
<ReferenceField source="productId" reference="products">
<TextField source="name" />
</ReferenceField>
<ReferenceField source="movementId" reference="stock-movements">
<TextField source="id" />
</ReferenceField>
<NumberField source="quantity" />
<BooleanField source="inStock" />
<DateField source="createdAt" />
<DateField source="updatedAt" />
</SimpleShowLayout>
</Show>
);

View File

@@ -0,0 +1,4 @@
export { StockMovementLineList } from './StockMovementLineList';
export { StockMovementLineEdit } from './StockMovementLineEdit';
export { StockMovementLineCreate } from './StockMovementLineCreate';
export { StockMovementLineShow } from './StockMovementLineShow';

View File

@@ -0,0 +1,18 @@
import { Create, SimpleForm, TextInput, DateInput, SelectInput } from 'react-admin';
const kindChoices = [
{ id: 'Receipt', name: 'Receipt' },
{ id: 'Issue', name: 'Issue' },
{ id: 'Transfer', name: 'Transfer' },
{ id: 'Adjustment', name: 'Adjustment' },
];
export const StockMovementCreate = () => (
<Create>
<SimpleForm>
<DateInput source="documentDate" />
<SelectInput source="kind" choices={kindChoices} />
<TextInput multiline source="comment" />
</SimpleForm>
</Create>
);

View File

@@ -0,0 +1,19 @@
import { Edit, SimpleForm, TextInput, DateInput, SelectInput } from 'react-admin';
const kindChoices = [
{ id: 'Receipt', name: 'Receipt' },
{ id: 'Issue', name: 'Issue' },
{ id: 'Transfer', name: 'Transfer' },
{ id: 'Adjustment', name: 'Adjustment' },
];
export const StockMovementEdit = () => (
<Edit>
<SimpleForm>
<TextInput disabled source="id" />
<DateInput source="documentDate" />
<SelectInput source="kind" choices={kindChoices} />
<TextInput multiline source="comment" />
</SimpleForm>
</Edit>
);

View File

@@ -0,0 +1,15 @@
import { List, DataTable, TextField, DateField, EditButton } from 'react-admin';
export const StockMovementList = () => (
<List>
<DataTable>
<DataTable.Col source="id" />
<DataTable.Col source="documentDate" field={DateField} />
<DataTable.Col source="kind" />
<DataTable.Col source="comment" />
<DataTable.Col source="createdAt" field={DateField} />
<DataTable.Col source="updatedAt" field={DateField} />
<DataTable.Col><EditButton /></DataTable.Col>
</DataTable>
</List>
);

View File

@@ -0,0 +1,14 @@
import { Show, SimpleShowLayout, TextField, DateField } from 'react-admin';
export const StockMovementShow = () => (
<Show>
<SimpleShowLayout>
<TextField source="id" />
<DateField source="documentDate" />
<TextField source="kind" />
<TextField source="comment" />
<DateField source="createdAt" />
<DateField source="updatedAt" />
</SimpleShowLayout>
</Show>
);

View File

@@ -0,0 +1,4 @@
export { StockMovementList } from './StockMovementList';
export { StockMovementEdit } from './StockMovementEdit';
export { StockMovementCreate } from './StockMovementCreate';
export { StockMovementShow } from './StockMovementShow';

View File

@@ -0,0 +1,13 @@
import { Create, SimpleForm, ReferenceInput, SelectInput, NumberInput, BooleanInput } from 'react-admin';
export const StockStatusCreate = () => (
<Create>
<SimpleForm>
<ReferenceInput source="productId" reference="products">
<SelectInput optionText="name" />
</ReferenceInput>
<NumberInput source="quantity" />
<BooleanInput source="inStock" />
</SimpleForm>
</Create>
);

View File

@@ -0,0 +1,13 @@
import { Edit, SimpleForm, ReferenceInput, SelectInput, NumberInput, BooleanInput } from 'react-admin';
export const StockStatusEdit = () => (
<Edit>
<SimpleForm>
<ReferenceInput source="productId" reference="products">
<SelectInput optionText="name" />
</ReferenceInput>
<NumberInput source="quantity" />
<BooleanInput source="inStock" />
</SimpleForm>
</Edit>
);

View File

@@ -0,0 +1,15 @@
import { List, DataTable, ReferenceField, TextField, NumberField, BooleanField, DateField, EditButton } from 'react-admin';
export const StockStatusList = () => (
<List>
<DataTable>
<DataTable.Col source="productId" field={ReferenceField} reference="products">
<TextField source="name" />
</DataTable.Col>
<DataTable.Col source="quantity" field={NumberField} />
<DataTable.Col source="inStock" field={BooleanField} />
<DataTable.Col source="updatedAt" field={DateField} />
<DataTable.Col><EditButton /></DataTable.Col>
</DataTable>
</List>
);

View File

@@ -0,0 +1,14 @@
import { Show, SimpleShowLayout, ReferenceField, TextField, NumberField, BooleanField, DateField } from 'react-admin';
export const StockStatusShow = () => (
<Show>
<SimpleShowLayout>
<ReferenceField source="productId" reference="products">
<TextField source="name" />
</ReferenceField>
<NumberField source="quantity" />
<BooleanField source="inStock" />
<DateField source="updatedAt" />
</SimpleShowLayout>
</Show>
);

View File

@@ -0,0 +1,4 @@
export { StockStatusList } from './StockStatusList';
export { StockStatusEdit } from './StockStatusEdit';
export { StockStatusCreate } from './StockStatusCreate';
export { StockStatusShow } from './StockStatusShow';