feat: add deleted flag to Store aggregate & ignore deleted stores while checking store name uniqueness #38
12 changed files with 103 additions and 70 deletions
|
@ -0,0 +1,19 @@
|
||||||
|
{
|
||||||
|
"db_name": "PostgreSQL",
|
||||||
|
"query": "INSERT INTO cqrs_inventory_store_query (\n version, name, address, store_id, owner, deleted\n ) VALUES (\n $1, $2, $3, $4, $5, $6\n );",
|
||||||
|
"describe": {
|
||||||
|
"columns": [],
|
||||||
|
"parameters": {
|
||||||
|
"Left": [
|
||||||
|
"Int8",
|
||||||
|
"Text",
|
||||||
|
"Text",
|
||||||
|
"Uuid",
|
||||||
|
"Uuid",
|
||||||
|
"Bool"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"nullable": []
|
||||||
|
},
|
||||||
|
"hash": "05ace802a2cd4162fee18286b56602494ae1d022bc9743d08e87c5ac1805f623"
|
||||||
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"db_name": "PostgreSQL",
|
"db_name": "PostgreSQL",
|
||||||
"query": "UPDATE\n cqrs_inventory_store_query\n SET\n version = $1,\n name = $2,\n address = $3,\n store_id = $4,\n owner = $5;",
|
"query": "UPDATE\n cqrs_inventory_store_query\n SET\n version = $1,\n name = $2,\n address = $3,\n store_id = $4,\n owner = $5,\n deleted = $6;",
|
||||||
"describe": {
|
"describe": {
|
||||||
"columns": [],
|
"columns": [],
|
||||||
"parameters": {
|
"parameters": {
|
||||||
|
@ -9,10 +9,11 @@
|
||||||
"Text",
|
"Text",
|
||||||
"Text",
|
"Text",
|
||||||
"Uuid",
|
"Uuid",
|
||||||
"Uuid"
|
"Uuid",
|
||||||
|
"Bool"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"nullable": []
|
"nullable": []
|
||||||
},
|
},
|
||||||
"hash": "48aa5f3eacaaec4a74ba5d2908875fcac797644d104d3d580715587ecb2e2119"
|
"hash": "0ccd86643c13d9d7c793f362aedc2d720d9dda982a0416849bf97291fc645ea5"
|
||||||
}
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"db_name": "PostgreSQL",
|
"db_name": "PostgreSQL",
|
||||||
"query": "SELECT \n name,\n description,\n image,\n product_id,\n category_id,\n price_major,\n price_minor,\n price_currency,\n sku_able\n FROM\n cqrs_inventory_product_query\n WHERE\n product_id = $1;",
|
"query": "SELECT \n name,\n description,\n image,\n product_id,\n category_id,\n price_major,\n price_minor,\n price_currency,\n sku_able,\n quantity_unit,\n quantity_number\n FROM\n cqrs_inventory_product_query\n WHERE\n product_id = $1;",
|
||||||
"describe": {
|
"describe": {
|
||||||
"columns": [
|
"columns": [
|
||||||
{
|
{
|
||||||
|
@ -47,6 +47,16 @@
|
||||||
"ordinal": 8,
|
"ordinal": 8,
|
||||||
"name": "sku_able",
|
"name": "sku_able",
|
||||||
"type_info": "Bool"
|
"type_info": "Bool"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ordinal": 9,
|
||||||
|
"name": "quantity_unit",
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ordinal": 10,
|
||||||
|
"name": "quantity_number",
|
||||||
|
"type_info": "Int4"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"parameters": {
|
"parameters": {
|
||||||
|
@ -63,8 +73,10 @@
|
||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
false
|
false
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"hash": "4389b997a21aa5184102aaf7c90fc527776e7a753b12bf7035904dedde904aae"
|
"hash": "398a5dc0ffc9f892255ebfd67e1583f5cf092d871a9a710ca4f59e14d08aaf8e"
|
||||||
}
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"db_name": "PostgreSQL",
|
"db_name": "PostgreSQL",
|
||||||
"query": "SELECT EXISTS (\n SELECT 1\n FROM cqrs_inventory_store_query\n WHERE\n name = $1\n );",
|
"query": "SELECT EXISTS (\n SELECT 1\n FROM cqrs_inventory_store_query\n WHERE\n name = $1\n AND\n deleted = false\n );",
|
||||||
"describe": {
|
"describe": {
|
||||||
"columns": [
|
"columns": [
|
||||||
{
|
{
|
||||||
|
@ -18,5 +18,5 @@
|
||||||
null
|
null
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"hash": "b84fb940a2aa673d3b19b2317e1e3436d3983e8a32400bbcefd91efb945190cd"
|
"hash": "56be64ebc41f5fc5bc0c6fbf06515798a2806685f5af8ba9f986a0835534b061"
|
||||||
}
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"db_name": "PostgreSQL",
|
"db_name": "PostgreSQL",
|
||||||
"query": "UPDATE\n cqrs_inventory_product_query\n SET\n version = $1,\n name = $2,\n description = $3,\n image = $4,\n product_id = $5,\n category_id = $6,\n price_major = $7,\n price_minor = $8,\n price_currency = $9,\n sku_able = $10;",
|
"query": "UPDATE\n cqrs_inventory_product_query\n SET\n version = $1,\n name = $2,\n description = $3,\n image = $4,\n product_id = $5,\n category_id = $6,\n price_major = $7,\n price_minor = $8,\n price_currency = $9,\n sku_able = $10,\n quantity_unit = $11,\n quantity_number = $12;",
|
||||||
"describe": {
|
"describe": {
|
||||||
"columns": [],
|
"columns": [],
|
||||||
"parameters": {
|
"parameters": {
|
||||||
|
@ -14,10 +14,12 @@
|
||||||
"Int4",
|
"Int4",
|
||||||
"Int4",
|
"Int4",
|
||||||
"Text",
|
"Text",
|
||||||
"Bool"
|
"Bool",
|
||||||
|
"Text",
|
||||||
|
"Int4"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"nullable": []
|
"nullable": []
|
||||||
},
|
},
|
||||||
"hash": "4d3524bb1742ba55267ab53322cf6c6942d6fc4057b65327f8c6d79ef21cc064"
|
"hash": "60fb3bb1d459b64f900cf02d7d2444b2183bd4d1a4af3a93336091f3c2bdcace"
|
||||||
}
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"db_name": "PostgreSQL",
|
"db_name": "PostgreSQL",
|
||||||
"query": "INSERT INTO cqrs_inventory_product_query (\n version,\n name,\n description,\n image,\n product_id,\n category_id,\n price_major,\n price_minor,\n price_currency,\n sku_able\n ) VALUES (\n $1, $2, $3, $4, $5, $6, $7, $8, $9, $10\n );",
|
"query": "INSERT INTO cqrs_inventory_product_query (\n version,\n name,\n description,\n image,\n product_id,\n category_id,\n price_major,\n price_minor,\n price_currency,\n sku_able,\n quantity_unit,\n quantity_number\n ) VALUES (\n $1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12\n );",
|
||||||
"describe": {
|
"describe": {
|
||||||
"columns": [],
|
"columns": [],
|
||||||
"parameters": {
|
"parameters": {
|
||||||
|
@ -14,10 +14,12 @@
|
||||||
"Int4",
|
"Int4",
|
||||||
"Int4",
|
"Int4",
|
||||||
"Text",
|
"Text",
|
||||||
"Bool"
|
"Bool",
|
||||||
|
"Text",
|
||||||
|
"Int4"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"nullable": []
|
"nullable": []
|
||||||
},
|
},
|
||||||
"hash": "3c82b22884858afc80ab013abddc072c816f5ea94eac454406f5eaa3129dd180"
|
"hash": "727e8a82469f1887a7136900d45cfb4e3b6c0ddeb0c3610ec5a9f80e0b1c227e"
|
||||||
}
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"db_name": "PostgreSQL",
|
"db_name": "PostgreSQL",
|
||||||
"query": "SELECT \n name, address, store_id, owner\n FROM\n cqrs_inventory_store_query\n WHERE\n store_id = $1;",
|
"query": "SELECT \n name, address, store_id, owner, deleted\n FROM\n cqrs_inventory_store_query\n WHERE\n store_id = $1;",
|
||||||
"describe": {
|
"describe": {
|
||||||
"columns": [
|
"columns": [
|
||||||
{
|
{
|
||||||
|
@ -22,6 +22,11 @@
|
||||||
"ordinal": 3,
|
"ordinal": 3,
|
||||||
"name": "owner",
|
"name": "owner",
|
||||||
"type_info": "Uuid"
|
"type_info": "Uuid"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ordinal": 4,
|
||||||
|
"name": "deleted",
|
||||||
|
"type_info": "Bool"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"parameters": {
|
"parameters": {
|
||||||
|
@ -33,8 +38,9 @@
|
||||||
false,
|
false,
|
||||||
true,
|
true,
|
||||||
false,
|
false,
|
||||||
|
false,
|
||||||
false
|
false
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"hash": "5385ba9531992b91670e52b5332af1f09069e1d6d168f9e93b729cf964e97c35"
|
"hash": "8019c47351303c392784405ac53a46c9ad10015d4afd5bba97d21eff71b12436"
|
||||||
}
|
}
|
|
@ -1,18 +0,0 @@
|
||||||
{
|
|
||||||
"db_name": "PostgreSQL",
|
|
||||||
"query": "INSERT INTO cqrs_inventory_store_query (\n version, name, address, store_id, owner\n ) VALUES (\n $1, $2, $3, $4, $5\n );",
|
|
||||||
"describe": {
|
|
||||||
"columns": [],
|
|
||||||
"parameters": {
|
|
||||||
"Left": [
|
|
||||||
"Int8",
|
|
||||||
"Text",
|
|
||||||
"Text",
|
|
||||||
"Uuid",
|
|
||||||
"Uuid"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"nullable": []
|
|
||||||
},
|
|
||||||
"hash": "89ebb8b413db2c4da15adff8a09d04d5849c3990f0965de479b76630317f8a6e"
|
|
||||||
}
|
|
|
@ -29,13 +29,30 @@ impl StoreIDExistsDBPort for InventoryDBPostgresAdapter {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
pub mod tests {
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
use crate::utils::uuid::tests::UUID;
|
use crate::utils::uuid::tests::UUID;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
|
pub async fn create_dummy_store_record(s: &Store, db: &InventoryDBPostgresAdapter) {
|
||||||
|
sqlx::query!(
|
||||||
|
"INSERT INTO cqrs_inventory_store_query
|
||||||
|
(version, name, address, store_id, owner, deleted)
|
||||||
|
VALUES ($1, $2, $3, $4, $5 ,$6);",
|
||||||
|
1,
|
||||||
|
s.name(),
|
||||||
|
s.address().as_ref().unwrap(),
|
||||||
|
s.store_id(),
|
||||||
|
s.owner(),
|
||||||
|
false
|
||||||
|
)
|
||||||
|
.execute(&db.pool)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
#[actix_rt::test]
|
#[actix_rt::test]
|
||||||
async fn test_postgres_store_exists() {
|
async fn test_postgres_store_exists() {
|
||||||
let store_id = Uuid::new_v4();
|
let store_id = Uuid::new_v4();
|
||||||
|
@ -58,19 +75,7 @@ mod tests {
|
||||||
// state doesn't exist
|
// state doesn't exist
|
||||||
assert!(!db.store_id_exists(&store).await.unwrap());
|
assert!(!db.store_id_exists(&store).await.unwrap());
|
||||||
|
|
||||||
sqlx::query!(
|
create_dummy_store_record(&store, &db).await;
|
||||||
"INSERT INTO cqrs_inventory_store_query
|
|
||||||
(version, name, address, store_id, owner)
|
|
||||||
VALUES ($1, $2, $3, $4, $5);",
|
|
||||||
1,
|
|
||||||
store.name(),
|
|
||||||
store.address().as_ref().unwrap(),
|
|
||||||
store.store_id(),
|
|
||||||
store.owner(),
|
|
||||||
)
|
|
||||||
.execute(&db.pool)
|
|
||||||
.await
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
// state exists
|
// state exists
|
||||||
assert!(db.store_id_exists(&store).await.unwrap());
|
assert!(db.store_id_exists(&store).await.unwrap());
|
||||||
|
|
|
@ -15,6 +15,8 @@ impl StoreNameExistsDBPort for InventoryDBPostgresAdapter {
|
||||||
FROM cqrs_inventory_store_query
|
FROM cqrs_inventory_store_query
|
||||||
WHERE
|
WHERE
|
||||||
name = $1
|
name = $1
|
||||||
|
AND
|
||||||
|
deleted = false
|
||||||
);",
|
);",
|
||||||
s.name(),
|
s.name(),
|
||||||
)
|
)
|
||||||
|
@ -35,6 +37,7 @@ mod tests {
|
||||||
use crate::utils::uuid::tests::UUID;
|
use crate::utils::uuid::tests::UUID;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
use crate::inventory::adapters::output::db::postgres::store_id_exists::tests::create_dummy_store_record;
|
||||||
|
|
||||||
#[actix_rt::test]
|
#[actix_rt::test]
|
||||||
async fn test_postgres_store_exists() {
|
async fn test_postgres_store_exists() {
|
||||||
|
@ -58,23 +61,21 @@ mod tests {
|
||||||
// state doesn't exist
|
// state doesn't exist
|
||||||
assert!(!db.store_name_exists(&store).await.unwrap());
|
assert!(!db.store_name_exists(&store).await.unwrap());
|
||||||
|
|
||||||
sqlx::query!(
|
create_dummy_store_record(&store, &db).await;
|
||||||
"INSERT INTO cqrs_inventory_store_query
|
|
||||||
(version, name, address, store_id, owner)
|
|
||||||
VALUES ($1, $2, $3, $4, $5);",
|
|
||||||
1,
|
|
||||||
store.name(),
|
|
||||||
store.address().as_ref().unwrap(),
|
|
||||||
store.store_id(),
|
|
||||||
store.owner(),
|
|
||||||
)
|
|
||||||
.execute(&db.pool)
|
|
||||||
.await
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
// state exists
|
// state exists
|
||||||
assert!(db.store_name_exists(&store).await.unwrap());
|
assert!(db.store_name_exists(&store).await.unwrap());
|
||||||
|
|
||||||
|
// Set store.deleted = true; now db.store_id_exists must return false
|
||||||
|
sqlx::query!(
|
||||||
|
"UPDATE cqrs_inventory_store_query SET deleted = true WHERE store_id = $1;",
|
||||||
|
store.store_id()
|
||||||
|
)
|
||||||
|
.execute(&db.pool)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
assert!(!db.store_name_exists(&store).await.unwrap());
|
||||||
|
|
||||||
settings.drop_db().await;
|
settings.drop_db().await;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,7 @@ pub struct StoreView {
|
||||||
address: Option<String>,
|
address: Option<String>,
|
||||||
store_id: Uuid,
|
store_id: Uuid,
|
||||||
owner: Uuid,
|
owner: Uuid,
|
||||||
|
deleted: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
// This updates the view with events as they are committed.
|
// This updates the view with events as they are committed.
|
||||||
|
@ -37,6 +38,7 @@ impl View<Store> for StoreView {
|
||||||
self.address = val.address().clone();
|
self.address = val.address().clone();
|
||||||
self.store_id = val.store_id().clone();
|
self.store_id = val.store_id().clone();
|
||||||
self.owner = val.owner().clone();
|
self.owner = val.owner().clone();
|
||||||
|
self.deleted = false;
|
||||||
}
|
}
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
|
@ -54,7 +56,7 @@ impl ViewRepository<StoreView, Store> for InventoryDBPostgresAdapter {
|
||||||
let res = sqlx::query_as!(
|
let res = sqlx::query_as!(
|
||||||
StoreView,
|
StoreView,
|
||||||
"SELECT
|
"SELECT
|
||||||
name, address, store_id, owner
|
name, address, store_id, owner, deleted
|
||||||
FROM
|
FROM
|
||||||
cqrs_inventory_store_query
|
cqrs_inventory_store_query
|
||||||
WHERE
|
WHERE
|
||||||
|
@ -79,7 +81,7 @@ impl ViewRepository<StoreView, Store> for InventoryDBPostgresAdapter {
|
||||||
let res = sqlx::query_as!(
|
let res = sqlx::query_as!(
|
||||||
StoreView,
|
StoreView,
|
||||||
"SELECT
|
"SELECT
|
||||||
name, address, store_id, owner
|
name, address, store_id, owner, deleted
|
||||||
FROM
|
FROM
|
||||||
cqrs_inventory_store_query
|
cqrs_inventory_store_query
|
||||||
WHERE
|
WHERE
|
||||||
|
@ -123,15 +125,16 @@ impl ViewRepository<StoreView, Store> for InventoryDBPostgresAdapter {
|
||||||
let version = context.version + 1;
|
let version = context.version + 1;
|
||||||
sqlx::query!(
|
sqlx::query!(
|
||||||
"INSERT INTO cqrs_inventory_store_query (
|
"INSERT INTO cqrs_inventory_store_query (
|
||||||
version, name, address, store_id, owner
|
version, name, address, store_id, owner, deleted
|
||||||
) VALUES (
|
) VALUES (
|
||||||
$1, $2, $3, $4, $5
|
$1, $2, $3, $4, $5, $6
|
||||||
);",
|
);",
|
||||||
version,
|
version,
|
||||||
view.name,
|
view.name,
|
||||||
view.address,
|
view.address,
|
||||||
view.store_id,
|
view.store_id,
|
||||||
view.owner,
|
view.owner,
|
||||||
|
view.deleted,
|
||||||
)
|
)
|
||||||
.execute(&self.pool)
|
.execute(&self.pool)
|
||||||
.await
|
.await
|
||||||
|
@ -147,12 +150,14 @@ impl ViewRepository<StoreView, Store> for InventoryDBPostgresAdapter {
|
||||||
name = $2,
|
name = $2,
|
||||||
address = $3,
|
address = $3,
|
||||||
store_id = $4,
|
store_id = $4,
|
||||||
owner = $5;",
|
owner = $5,
|
||||||
|
deleted = $6;",
|
||||||
version,
|
version,
|
||||||
view.name,
|
view.name,
|
||||||
view.address,
|
view.address,
|
||||||
view.store_id,
|
view.store_id,
|
||||||
view.owner,
|
view.owner,
|
||||||
|
view.deleted,
|
||||||
)
|
)
|
||||||
.execute(&self.pool)
|
.execute(&self.pool)
|
||||||
.await
|
.await
|
||||||
|
|
|
@ -22,6 +22,8 @@ pub struct Store {
|
||||||
address: Option<String>,
|
address: Option<String>,
|
||||||
owner: Uuid,
|
owner: Uuid,
|
||||||
store_id: Uuid,
|
store_id: Uuid,
|
||||||
|
#[builder(default = "false")]
|
||||||
|
deleted: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
|
@ -49,11 +51,6 @@ impl Aggregate for Store {
|
||||||
Ok(vec![InventoryEvent::StoreAdded(res)])
|
Ok(vec![InventoryEvent::StoreAdded(res)])
|
||||||
}
|
}
|
||||||
_ => Ok(Vec::default()),
|
_ => Ok(Vec::default()),
|
||||||
// InventoryCommand::AddCategory(cmd) => {
|
|
||||||
// let res = services.add_category().add_store(cmd).await?;
|
|
||||||
// Ok(vec![InventoryEvent::CategoryAdded(res)])
|
|
||||||
//
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,6 +61,7 @@ impl Aggregate for Store {
|
||||||
self.address = e.address().as_ref().map(|s| s.to_string());
|
self.address = e.address().as_ref().map(|s| s.to_string());
|
||||||
self.owner = e.owner().clone();
|
self.owner = e.owner().clone();
|
||||||
self.store_id = e.store_id().clone();
|
self.store_id = e.store_id().clone();
|
||||||
|
self.deleted = false;
|
||||||
}
|
}
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue