Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merge dev to main #1

Merged
merged 9 commits into from
Dec 17, 2021
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Prev Previous commit
Next Next commit
Implement article crud
  • Loading branch information
FrozyPenguin committed Dec 16, 2021
commit ec45a7f8f9427105794e751578146e4d77cfc876
11 changes: 11 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
"@types/better-sqlite3": "^7.4.1",
"@types/sqlite3": "^3.1.7",
"better-sqlite3": "^7.4.5",
"class-transformer": "^0.5.1",
"class-validator": "^0.13.2",
"cors": "^2.8.5",
"express": "^4.17.1",
Expand Down
209 changes: 140 additions & 69 deletions src/controllers/ArticlesCtrl.ts
Original file line number Diff line number Diff line change
@@ -1,89 +1,160 @@
import { validate, ValidationError } from 'class-validator';
import { plainToInstance } from 'class-transformer';
import { NextFunction, Request, Response } from 'express';
import { getRepository, Repository } from 'typeorm';
import { Article, ArticleType } from '../models/Article';
import { Article } from '../models/Article';

const ArticleRepository: Repository<Article> = getRepository(Article);

export async function getArticles(req: Request, res: Response, next: NextFunction) {
export function getArticles(req: Request, res: Response, next: NextFunction) {
// Test: 'curl http://localhost:3000/api/GPAO/Articles'
res.json(await ArticleRepository.find());
ArticleRepository.find().then(articles => res.status(200).json(articles))
.catch(error => {
console.error(error);
return res
.status(500)
.json({
error: 500,
message: 'Erreur au niveau de votre demande !'
});
});
}

export async function getArticle(req: Request, res: Response, next: NextFunction) {
const article = await ArticleRepository.findOne(req.params.reference);
console.log(req.params.reference);
console.log(article);
if(!article) {
res
.status(404)
export function getArticle(req: Request, res: Response, next: NextFunction) {
ArticleRepository.findOne(req.params.reference)
.then(article => {
if(!article) {
return res
.status(404)
.json({
error: 404,
param: req.params.reference,
message: 'Article not found !'
});
}
res.status(200).json(article);
})
.catch(error => {
console.error(error);
return res
.status(500)
.json({
error: 404,
param: req.params.reference,
message: 'Article not found !'
error: 500,
message: 'Erreur au niveau de votre demande !'
});
}
res.send(article);
});
}

export function addArticle(req: Request, res: Response, next: NextFunction) {
/* Création article (Windows 10) :
$CC201 = @{
reference = 'CC201'
designation = 'Camion citerne rouge'
type_fabrication_achat = 'Fab. a la commande'
unite_achat_stock = 'unite'
delai_en_semaine = 2
lot_de_reapprovisionnement = 150
stock_maxi = 600
PF_ou_MP_ou_Piece_ou_SE = 'PF'
}|ConvertTo-Json
echo $CC201
*/
/* (Windows 10) :
$Nouvel_article = @{
Body = $CC201
ContentType = 'application/json'
Method = 'POST'
Uri = 'http://localhost:1963/api/GPAO/Nouvel_article'
}
*/
/* (Windows 10) :
Invoke-RestMethod @Nouvel_article
*/
// TODO: Pour faire des ajout encapsulé peut etre problème
export async function addArticle(req: Request, res: Response, next: NextFunction) {
// console.log(JSON.stringify(request.body));
const article: Article = req.body;
const article: Article = plainToInstance(Article, req.body);

// const { error, value } = articles.validate({
// reference: article.reference, // Unicity required as well...
// designation: article.designation, // Unicity required as well...
// type_fabrication_achat: article.type_fabrication_achat,
// unite_achat_stock: article.unite_achat_stock,
// delai_en_semaine: article.delai_en_semaine,
// lot_de_reapprovisionnement: article.lot_de_reapprovisionnement,
// stock_maxi: article.stock_maxi,
// PF_ou_MP_ou_Piece_ou_SE: article.PF_ou_MP_ou_Piece_ou_SE,
// });
try {
const errors: ValidationError[] = await validate(article, { skipMissingProperties: true });
if(errors.length > 0) {
return res
.status(400)
.json({
error: 400,
message: `Article invalidé (échec) : ${ errors.map(error => error.toString()).join(', ') }`
});
}

// if (error === undefined) {
// res.status(201).json({
// message: 'Article validé (succès) : ' + value.reference,
// });
// Articles.push(article);
// } else {
// res.status(400).json({
// message: 'Article invalidé (échec) : ' + error.message,
// });
// }
const savedArticles: Article = await ArticleRepository.save(article);
return res
.status(201)
.json({
message: 'Article validé (succès) : ' + savedArticles.reference,
});
}
catch(error) {
return res
.status(500)
.json({
error: 500,
message: `Erreur au niveau de votre demande !`
});
}
}

export function deleteArticle(req: Request, res: Response, next: NextFunction) {
res.status(500).json({
error: 'Not yet implemented !',
});
export async function deleteArticle(req: Request, res: Response, next: NextFunction) {
try {
const article = await ArticleRepository.findOne(req.params.reference);

if(!article) {
return res
.status(404)
.json({
error: 404,
param: req.params.reference,
message: 'Article not found !'
});
}

const removeArticle = await ArticleRepository.remove(article as Article);
return res
.status(200)
.json({
message: 'Article supprimé (succès) : ' + removeArticle.reference || req.params.reference,
});
}
catch(error) {
console.error(error);
return res
.status(500)
.json({
error: 500,
message: 'Erreur au niveau de votre demande !'
});
}
}

export function updateArticle(req: Request, res: Response, next: NextFunction) {
res.status(500).json({
error: 'Not yet implemented !',
});
export async function updateArticle(req: Request, res: Response, next: NextFunction) {
try {
const articleToUpdate = await ArticleRepository.findOne(req.params.reference);

if(!articleToUpdate) {
return res
.status(404)
.json({
error: 404,
param: req.params.reference,
message: 'Article not found !'
});
}

const article: Article = plainToInstance(Article, {
...articleToUpdate,
...req.body
});

console.log(article)

const errors: ValidationError[] = await validate(article, { skipMissingProperties: true });
if(errors.length > 0) {
return res
.status(400)
.json({
error: 400,
message: `Article invalidé (échec) : ${ errors.map(error => error.toString()).join(', ') }`
});
}

const updatedArticles: Article = await ArticleRepository.save(article);
return res
.status(201)
.json({
message: 'Article mis à jour (succès) : ' + updatedArticles.reference,
});
}
catch(error) {
console.error(error);
return res
.status(500)
.json({
error: 500,
message: 'Erreur au niveau de votre demande !'
});
}
}
4 changes: 2 additions & 2 deletions src/database/dbDropper.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import * as fs from 'fs';
import * as Database from 'better-sqlite3';

const db = new Database('src/database/gpao.sqlite', { verbose: console.log });
const db = new Database('./gpao.sqlite', { verbose: console.log });

const migration = fs.readFileSync(
'src/database/GPAO.SQLite_deletion.sql',
'./GPAO.SQLite_deletion.sql',
'utf8'
);
db.exec(migration);
Expand Down
2 changes: 2 additions & 0 deletions src/database/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import 'reflect-metadata';
import { createConnection, ConnectionOptions, Connection } from 'typeorm';
import * as path from 'path';
import { resetDatabase } from '../utils/resetDatabase';

let connection: Connection | null;

Expand All @@ -13,6 +14,7 @@ const options: ConnectionOptions = {

async function connect() {
try {
await resetDatabase(path.resolve(__dirname, './gpao.sqlite'), path.resolve(__dirname, './GPAO.SQLite_creation.sql'));
connection = await createConnection(options);
}
catch(e) {
Expand Down
29 changes: 22 additions & 7 deletions src/models/Article.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,21 +33,21 @@ export class Article {
unique: true,
})
@IsString()
@IsAlphanumeric()
@Matches(new RegExp('^[a-zA-Z0-9. ]*$'))
@MaxLength(30)
@IsDefined()
designation!: string;

@Column("varchar", { name: "type_fabrication_achat", length: 30 })
@IsString()
@IsAlphanumeric()
@Matches(new RegExp('^[a-zA-Z0-9. ]*$'))
@MaxLength(30)
@IsDefined()
typeFabricationAchat!: string;

@Column("varchar", { name: "unite_achat_stock", length: 30 })
@IsString()
@IsAlphanumeric()
@Matches(new RegExp('^[a-zA-Z0-9. ]*$'))
@MaxLength(30)
@IsDefined()
uniteAchatStock!: string;
Expand Down Expand Up @@ -98,25 +98,40 @@ export class Article {

@OneToMany(
() => LienDeNomenclature,
(lienDeNomenclature) => lienDeNomenclature.composant
(lienDeNomenclature) => lienDeNomenclature.composant,
{
eager: true
}
)
@ValidateNested()
composants!: LienDeNomenclature[];

@OneToMany(
() => LienDeNomenclature,
(lienDeNomenclature) => lienDeNomenclature.compose
(lienDeNomenclature) => lienDeNomenclature.compose,
{
eager: true
}
)
@ValidateNested()
composes!: LienDeNomenclature[];

@OneToMany(() => Operation, (operation) => operation.reference)
@OneToMany(
() => Operation,
(operation) => operation.reference,
{
eager: true
}
)
@ValidateNested()
operations!: Operation[];

@OneToMany(
() => MouvementDeStock,
(mouvementDeStock) => mouvementDeStock.reference
(mouvementDeStock) => mouvementDeStock.reference,
{
eager: true
}
)
@ValidateNested()
mouvementDeStocks!: MouvementDeStock[];
Expand Down
12 changes: 9 additions & 3 deletions src/models/LienDeNomenclature.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,20 +17,26 @@ export class LienDeNomenclature {
quantiteDeComposition!: number;

@ManyToOne(() => Article, (article) => article.composants, {
onDelete: "CASCADE",
onDelete: "CASCADE"
})
@JoinColumn([{ name: "composant", referencedColumnName: "reference" }])
@ValidateNested()
composant!: Article;

@ManyToOne(() => Article, (article) => article.composes, {
onDelete: "CASCADE",
onDelete: "CASCADE"
})
@JoinColumn([{ name: "compose", referencedColumnName: "reference" }])
@ValidateNested()
compose!: Article;

@OneToMany(() => Remplacement, (remplacement) => remplacement.remplace)
@OneToMany(
() => Remplacement,
(remplacement) => remplacement.remplace,
{
eager: true
}
)
@ValidateNested()
remplacements!: Remplacement[];
}
Loading