Added data label for backend.
This commit is contained in:
@@ -33,7 +33,7 @@ fn from_postgres_row_small(row: PgRow) -> Article {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async fn from_postgres_row(row: PgRow, pool: PgPool) -> Article {
|
async fn from_postgres_row(row: PgRow, pool: PgPool) -> Article {
|
||||||
let variants_option = load_article_variants(row.get(0), pool).await;
|
let variants_option = load_article_variants(row.get(0), &pool).await;
|
||||||
|
|
||||||
let variants = match variants_option {
|
let variants = match variants_option {
|
||||||
Some(variants_inner) => {
|
Some(variants_inner) => {
|
||||||
|
|||||||
@@ -0,0 +1,148 @@
|
|||||||
|
use log::{error, info};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use sqlx::{Arguments, Decode, Encode, FromRow, PgPool, Row};
|
||||||
|
use sqlx::postgres::{PgArguments, PgRow};
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize, Serialize, Clone, FromRow, Decode, Encode)]
|
||||||
|
pub struct Label {
|
||||||
|
pub id: i64,
|
||||||
|
pub name: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn from_postgres_row_small(row: PgRow) -> Label {
|
||||||
|
Label {
|
||||||
|
id: row.get(0),
|
||||||
|
name: row.get(1),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn load_labels(pool: PgPool) -> Option<Vec<Label>> {
|
||||||
|
let statement = format!(
|
||||||
|
"SELECT * FROM {}",
|
||||||
|
"label",
|
||||||
|
);
|
||||||
|
|
||||||
|
let res = sqlx::query(
|
||||||
|
statement.as_str())
|
||||||
|
.fetch_all(&pool).await;
|
||||||
|
|
||||||
|
let mut labels: Vec<Label> = Vec::new();
|
||||||
|
|
||||||
|
match res {
|
||||||
|
Ok(records) => {
|
||||||
|
for record in records {
|
||||||
|
labels.push(
|
||||||
|
from_postgres_row_small(record)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Some(labels)
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
|
error!("Error while loading all labels");
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn load_label(id: i64, pool: &PgPool) -> Option<Label> {
|
||||||
|
let statement = format!(
|
||||||
|
"SELECT * FROM {} WHERE $1 = id",
|
||||||
|
"label",
|
||||||
|
);
|
||||||
|
|
||||||
|
let mut args = PgArguments::default();
|
||||||
|
args.add(id);
|
||||||
|
|
||||||
|
let res = sqlx::query_with(
|
||||||
|
statement.as_str(), args)
|
||||||
|
.fetch_one(pool).await;
|
||||||
|
|
||||||
|
match res {
|
||||||
|
Ok(record) => {
|
||||||
|
Some(from_postgres_row_small(record))
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
|
error!("Error while loading label: {}", id);
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn insert_label(label: &Label, pool: PgPool) -> Option<Label> {
|
||||||
|
let mut args = PgArguments::default();
|
||||||
|
args.add(&label.name);
|
||||||
|
|
||||||
|
let statement = format!(
|
||||||
|
"INSERT INTO {} (name) VALUES ($1) RETURNING *",
|
||||||
|
"label",
|
||||||
|
);
|
||||||
|
|
||||||
|
let res = sqlx::query_with(
|
||||||
|
statement.as_str(),
|
||||||
|
args)
|
||||||
|
.fetch_one(&pool).await;
|
||||||
|
|
||||||
|
info!("{:#?}", res);
|
||||||
|
|
||||||
|
match res {
|
||||||
|
Ok(record) => {
|
||||||
|
let label = from_postgres_row_small(record);
|
||||||
|
|
||||||
|
Some(label)
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
|
error!("Error while loading newly created label: {}", label.name);
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn update_label(label_id: i64, label: &Label, pool: PgPool) -> Option<Label> {
|
||||||
|
let mut args = PgArguments::default();
|
||||||
|
args.add(&label.id);
|
||||||
|
args.add(&label.name);
|
||||||
|
|
||||||
|
let statement = format!(
|
||||||
|
"UPDATE {} SET name = $2 WHERE id = $1 RETURNING *",
|
||||||
|
"label",
|
||||||
|
);
|
||||||
|
|
||||||
|
let res = sqlx::query_with(
|
||||||
|
statement.as_str(),
|
||||||
|
args)
|
||||||
|
.fetch_one(&pool).await;
|
||||||
|
|
||||||
|
info!("{:#?}", res);
|
||||||
|
|
||||||
|
match res {
|
||||||
|
Ok(record) => {
|
||||||
|
let label = from_postgres_row_small(record);
|
||||||
|
Some(label)
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
|
error!("Error while updating label: {}", label_id);
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn delete_label(label_id: i64, pool: PgPool) -> Option<()> {
|
||||||
|
let result = sqlx::query(
|
||||||
|
format!("DELETE FROM {} WHERE id = {}",
|
||||||
|
"label",
|
||||||
|
label_id
|
||||||
|
).as_str()
|
||||||
|
).execute(&pool).await;
|
||||||
|
|
||||||
|
match result {
|
||||||
|
Ok(_) => {
|
||||||
|
Some(())
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
|
println!("Error deleting label: {:#?}", err);
|
||||||
|
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,3 +2,4 @@ pub mod origin;
|
|||||||
pub mod article;
|
pub mod article;
|
||||||
pub mod variant;
|
pub mod variant;
|
||||||
pub mod unit;
|
pub mod unit;
|
||||||
|
pub mod label;
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ use log::{error, info};
|
|||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use sqlx::{Arguments, FromRow, PgPool, Row};
|
use sqlx::{Arguments, FromRow, PgPool, Row};
|
||||||
use sqlx::postgres::{PgArguments, PgRow};
|
use sqlx::postgres::{PgArguments, PgRow};
|
||||||
|
use crate::models::label::{load_label, Label};
|
||||||
use crate::models::unit::Unit;
|
use crate::models::unit::Unit;
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize, Clone, FromRow)]
|
#[derive(Debug, Deserialize, Serialize, Clone, FromRow)]
|
||||||
@@ -13,9 +14,13 @@ pub struct Variant {
|
|||||||
pub description: Option<String>,
|
pub description: Option<String>,
|
||||||
pub ingredients: Option<String>,
|
pub ingredients: Option<String>,
|
||||||
pub unit: Unit,
|
pub unit: Unit,
|
||||||
|
pub label: Option<Label>,
|
||||||
|
pub variant_description: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn from_postgres_row_small(row: PgRow) -> Variant {
|
async fn from_postgres_row(row: PgRow, pool: &PgPool) -> Variant {
|
||||||
|
let label = load_label(row.get(0), pool).await;
|
||||||
|
|
||||||
Variant {
|
Variant {
|
||||||
id: row.get(0),
|
id: row.get(0),
|
||||||
weight: row.get(2),
|
weight: row.get(2),
|
||||||
@@ -24,10 +29,12 @@ fn from_postgres_row_small(row: PgRow) -> Variant {
|
|||||||
description: row.get(5),
|
description: row.get(5),
|
||||||
ingredients: row.get(6),
|
ingredients: row.get(6),
|
||||||
unit: row.get(7),
|
unit: row.get(7),
|
||||||
|
label: label,
|
||||||
|
variant_description: row.get(9),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn load_article_variants(article_id: i64, pool: PgPool) -> Option<Vec<Variant>> {
|
pub async fn load_article_variants(article_id: i64, pool: &PgPool) -> Option<Vec<Variant>> {
|
||||||
let statement = format!(
|
let statement = format!(
|
||||||
"SELECT * FROM {} WHERE article_id = $1",
|
"SELECT * FROM {} WHERE article_id = $1",
|
||||||
"variant",
|
"variant",
|
||||||
@@ -38,7 +45,7 @@ pub async fn load_article_variants(article_id: i64, pool: PgPool) -> Option<Vec<
|
|||||||
|
|
||||||
let res = sqlx::query_with(
|
let res = sqlx::query_with(
|
||||||
statement.as_str(), args)
|
statement.as_str(), args)
|
||||||
.fetch_all(&pool).await;
|
.fetch_all(pool).await;
|
||||||
|
|
||||||
let mut variants: Vec<Variant> = Vec::new();
|
let mut variants: Vec<Variant> = Vec::new();
|
||||||
|
|
||||||
@@ -46,7 +53,7 @@ pub async fn load_article_variants(article_id: i64, pool: PgPool) -> Option<Vec<
|
|||||||
Ok(records) => {
|
Ok(records) => {
|
||||||
for record in records {
|
for record in records {
|
||||||
variants.push(
|
variants.push(
|
||||||
from_postgres_row_small(record)
|
from_postgres_row(record, &pool).await
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -60,6 +67,15 @@ pub async fn load_article_variants(article_id: i64, pool: PgPool) -> Option<Vec<
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub async fn insert_variant(article_id: i64, variant: &Variant, pool: PgPool) -> Option<Variant> {
|
pub async fn insert_variant(article_id: i64, variant: &Variant, pool: PgPool) -> Option<Variant> {
|
||||||
|
let label_id = match &variant.label {
|
||||||
|
Some(label) => {
|
||||||
|
Some(label.id)
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
let mut args = PgArguments::default();
|
let mut args = PgArguments::default();
|
||||||
args.add(&article_id);
|
args.add(&article_id);
|
||||||
args.add(&variant.weight);
|
args.add(&variant.weight);
|
||||||
@@ -68,9 +84,11 @@ pub async fn insert_variant(article_id: i64, variant: &Variant, pool: PgPool) ->
|
|||||||
args.add(&variant.description);
|
args.add(&variant.description);
|
||||||
args.add(&variant.ingredients);
|
args.add(&variant.ingredients);
|
||||||
args.add(&variant.unit);
|
args.add(&variant.unit);
|
||||||
|
args.add(label_id);
|
||||||
|
args.add(&variant.variant_description);
|
||||||
|
|
||||||
let statement = format!(
|
let statement = format!(
|
||||||
"INSERT INTO {} (article_id, weight, ean, name, description, ingredients, unit_id) VALUES ($1, $2, $3, $4, $5, $6, $7) RETURNING *",
|
"INSERT INTO {} (article_id, weight, ean, name, description, ingredients, unit_id, label_id, variant_description) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9) RETURNING *",
|
||||||
"variant",
|
"variant",
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -83,7 +101,7 @@ pub async fn insert_variant(article_id: i64, variant: &Variant, pool: PgPool) ->
|
|||||||
|
|
||||||
match res {
|
match res {
|
||||||
Ok(record) => {
|
Ok(record) => {
|
||||||
let variant = from_postgres_row_small(record);
|
let variant = from_postgres_row(record, &pool).await;
|
||||||
Some(variant)
|
Some(variant)
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
@@ -94,6 +112,15 @@ pub async fn insert_variant(article_id: i64, variant: &Variant, pool: PgPool) ->
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub async fn update_variant(variant_id: i64, variant: &Variant, pool: PgPool) -> Option<Variant> {
|
pub async fn update_variant(variant_id: i64, variant: &Variant, pool: PgPool) -> Option<Variant> {
|
||||||
|
let label_id = match &variant.label {
|
||||||
|
Some(label) => {
|
||||||
|
Some(label.id)
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
let mut args = PgArguments::default();
|
let mut args = PgArguments::default();
|
||||||
args.add(&variant.id);
|
args.add(&variant.id);
|
||||||
args.add(&variant.weight);
|
args.add(&variant.weight);
|
||||||
@@ -102,11 +129,13 @@ pub async fn update_variant(variant_id: i64, variant: &Variant, pool: PgPool) ->
|
|||||||
args.add(&variant.description);
|
args.add(&variant.description);
|
||||||
args.add(&variant.ingredients);
|
args.add(&variant.ingredients);
|
||||||
args.add(&variant.unit);
|
args.add(&variant.unit);
|
||||||
|
args.add(label_id);
|
||||||
|
args.add(&variant.variant_description);
|
||||||
|
|
||||||
info!("Variant: {:#?}", variant);
|
info!("Variant: {:#?}", variant);
|
||||||
|
|
||||||
let statement = format!(
|
let statement = format!(
|
||||||
"UPDATE {} SET weight = $2, ean = $3, name = $4, description = $5, ingredients = $6, unit_id = $7 WHERE id = $1 RETURNING *",
|
"UPDATE {} SET weight = $2, ean = $3, name = $4, description = $5, ingredients = $6, unit_id = $7, label_id = $8, variant_description = $9 WHERE id = $1 RETURNING *",
|
||||||
"variant",
|
"variant",
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -119,7 +148,7 @@ pub async fn update_variant(variant_id: i64, variant: &Variant, pool: PgPool) ->
|
|||||||
|
|
||||||
match res {
|
match res {
|
||||||
Ok(record) => {
|
Ok(record) => {
|
||||||
let variant = from_postgres_row_small(record);
|
let variant = from_postgres_row(record, &pool).await;
|
||||||
Some(variant)
|
Some(variant)
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
import {Variant} from "~/types/variant";
|
import {Variant} from "~/types/variant";
|
||||||
import DeleteConfirm from "~/components/ui/deleteConfirm.vue";
|
import DeleteConfirm from "~/components/ui/deleteConfirm.vue";
|
||||||
import type {Unit} from "~/types/unit";
|
import type {Unit} from "~/types/unit";
|
||||||
|
import type {Label} from "~/types/label";
|
||||||
|
|
||||||
let store = useLabelEditorStore();
|
let store = useLabelEditorStore();
|
||||||
|
|
||||||
@@ -19,6 +20,8 @@
|
|||||||
let unit: Ref<Unit | null> = ref<Unit | null>(JSON.parse(JSON.stringify(props.variant.unit)));
|
let unit: Ref<Unit | null> = ref<Unit | null>(JSON.parse(JSON.stringify(props.variant.unit)));
|
||||||
let description: Ref<string | null> = ref<string | null>(JSON.parse(JSON.stringify(props.variant.description)));
|
let description: Ref<string | null> = ref<string | null>(JSON.parse(JSON.stringify(props.variant.description)));
|
||||||
let ingredients: Ref<string | null> = ref<string | null>(JSON.parse(JSON.stringify(props.variant.ingredients)));
|
let ingredients: Ref<string | null> = ref<string | null>(JSON.parse(JSON.stringify(props.variant.ingredients)));
|
||||||
|
let label: Ref<Label | null> = ref<Label | null>(JSON.parse(JSON.stringify(props.variant.label)));
|
||||||
|
let variant_description: Ref<string | null> = ref<string | null>(JSON.parse(JSON.stringify(props.variant.variant_description)));
|
||||||
|
|
||||||
function toggleEdit() {
|
function toggleEdit() {
|
||||||
if (edit.value) {
|
if (edit.value) {
|
||||||
@@ -44,7 +47,9 @@
|
|||||||
|
|
||||||
async function updateVariant() {
|
async function updateVariant() {
|
||||||
if (weight.value != null && unit.value != null) {
|
if (weight.value != null && unit.value != null) {
|
||||||
let updateVariant: Variant = new Variant(props.variant.id, weight.value, ean.value, name.value, description.value, ingredients.value, unit.value);
|
let updateVariant: Variant = new Variant(props.variant.id, weight.value,
|
||||||
|
ean.value, name.value, description.value, ingredients.value,
|
||||||
|
unit.value, label.value, variant_description.value);
|
||||||
|
|
||||||
await store.updateVariant(updateVariant);
|
await store.updateVariant(updateVariant);
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
export class Label {
|
||||||
|
readonly id: number;
|
||||||
|
name: string;
|
||||||
|
|
||||||
|
constructor(id: number, name: string) {
|
||||||
|
this.id = id;
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
import type {Unit} from "~/types/unit";
|
import type {Unit} from "~/types/unit";
|
||||||
|
import type {Label} from "~/types/label";
|
||||||
|
|
||||||
export class Variant {
|
export class Variant {
|
||||||
readonly id: number;
|
readonly id: number;
|
||||||
@@ -8,8 +9,12 @@ export class Variant {
|
|||||||
description: string | null;
|
description: string | null;
|
||||||
ingredients: string | null;
|
ingredients: string | null;
|
||||||
unit: Unit;
|
unit: Unit;
|
||||||
|
label: Label | null;
|
||||||
|
variant_description: string | null;
|
||||||
|
|
||||||
constructor(id: number, weight: string, ean: string|null, name: string|null, description:string|null, ingredients: string|null, unit: Unit) {
|
constructor(id: number, weight: string, ean: string|null, name: string|null,
|
||||||
|
description:string|null, ingredients: string|null, unit: Unit,
|
||||||
|
label: Label | null, variant_description: string | null) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.weight = weight;
|
this.weight = weight;
|
||||||
this.ean = ean;
|
this.ean = ean;
|
||||||
@@ -17,5 +22,7 @@ export class Variant {
|
|||||||
this.description = description;
|
this.description = description;
|
||||||
this.ingredients = ingredients;
|
this.ingredients = ingredients;
|
||||||
this.unit = unit;
|
this.unit = unit;
|
||||||
|
this.label = label;
|
||||||
|
this.variant_description = variant_description;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
-- Add migration script here
|
||||||
|
|
||||||
|
-- Create Label
|
||||||
|
CREATE TABLE label
|
||||||
|
(
|
||||||
|
id bigint NOT NULL GENERATED ALWAYS AS IDENTITY ( INCREMENT 1 START 1 ),
|
||||||
|
name text NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Alter variant table
|
||||||
|
ALTER TABLE public.variant
|
||||||
|
ADD label_id bigint,
|
||||||
|
ADD variant_description text,
|
||||||
|
ADD CONSTRAINT variant_label_id_fkey
|
||||||
|
foreign key (label_id)
|
||||||
|
references unit(id)
|
||||||
|
ON DELETE NO ACTION;
|
||||||
@@ -211,6 +211,8 @@ async fn add_variant(
|
|||||||
description: None,
|
description: None,
|
||||||
ingredients: None,
|
ingredients: None,
|
||||||
unit: Unit::G,
|
unit: Unit::G,
|
||||||
|
label: None,
|
||||||
|
variant_description: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
(StatusCode::INTERNAL_SERVER_ERROR, Json(variant))
|
(StatusCode::INTERNAL_SERVER_ERROR, Json(variant))
|
||||||
@@ -240,6 +242,8 @@ async fn update_variant_route(
|
|||||||
description: None,
|
description: None,
|
||||||
ingredients: None,
|
ingredients: None,
|
||||||
unit: Unit::G,
|
unit: Unit::G,
|
||||||
|
label: None,
|
||||||
|
variant_description: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
(StatusCode::INTERNAL_SERVER_ERROR, Json(variant))
|
(StatusCode::INTERNAL_SERVER_ERROR, Json(variant))
|
||||||
|
|||||||
Reference in New Issue
Block a user