Test create address, handle phone number
This commit is contained in:
parent
7617cb1064
commit
4087b2c3ee
@ -27,7 +27,7 @@ pub(crate) async fn account_addresses(
|
||||
) -> Result<Vec<model::AccountAddress>> {
|
||||
sqlx::query_as(
|
||||
r#"
|
||||
SELECT id, name, email, street, city, country, zip, account_id, is_default
|
||||
SELECT id, name, email, phone, street, city, country, zip, account_id, is_default
|
||||
FROM account_addresses
|
||||
WHERE account_id = $1
|
||||
"#,
|
||||
@ -37,7 +37,6 @@ WHERE account_id = $1
|
||||
.await
|
||||
.map_err(|_| Error::AccountAddresses.into())
|
||||
}
|
||||
////
|
||||
|
||||
#[derive(actix::Message)]
|
||||
#[rtype(result = "Result<model::AccountAddress>")]
|
||||
@ -59,7 +58,7 @@ pub(crate) async fn find_account_address(
|
||||
) -> Result<model::AccountAddress> {
|
||||
sqlx::query_as(
|
||||
r#"
|
||||
SELECT id, name, email, street, city, country, zip, account_id, is_default
|
||||
SELECT id, name, email, phone, street, city, country, zip, account_id, is_default
|
||||
FROM account_addresses
|
||||
WHERE account_id = $1 AND id = $2
|
||||
"#,
|
||||
@ -92,7 +91,7 @@ pub(crate) async fn default_account_address(
|
||||
) -> Result<model::AccountAddress> {
|
||||
sqlx::query_as(
|
||||
r#"
|
||||
SELECT id, name, email, street, city, country, zip, account_id, is_default
|
||||
SELECT id, name, email, phone, street, city, country, zip, account_id, is_default
|
||||
FROM account_addresses
|
||||
WHERE account_id = $1 AND is_default
|
||||
"#,
|
||||
@ -108,6 +107,7 @@ WHERE account_id = $1 AND is_default
|
||||
pub struct CreateAccountAddress {
|
||||
pub name: model::Name,
|
||||
pub email: model::Email,
|
||||
pub phone: model::Phone,
|
||||
pub street: model::Street,
|
||||
pub city: model::City,
|
||||
pub country: model::Country,
|
||||
@ -127,7 +127,7 @@ pub(crate) async fn create_address(
|
||||
msg: CreateAccountAddress,
|
||||
pool: &mut sqlx::Transaction<'_, sqlx::Postgres>,
|
||||
) -> Result<model::AccountAddress> {
|
||||
if msg.is_default {
|
||||
if msg.is_default && msg.account_id.is_some() {
|
||||
if let Err(e) = sqlx::query(
|
||||
r#"
|
||||
UPDATE account_addresses
|
||||
@ -142,20 +142,23 @@ WHERE account_id = $1
|
||||
log::error!("{}", e);
|
||||
}
|
||||
}
|
||||
|
||||
sqlx::query_as(
|
||||
r#"
|
||||
INSERT INTO account_addresses ( name, email, street, city, country, zip, account_id )
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7)
|
||||
RETURNING id, name, email, street, city, country, zip, account_id, is_default
|
||||
INSERT INTO account_addresses ( name, email, phone, street, city, country, zip, account_id )
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7, $8)
|
||||
RETURNING id, name, email, phone, street, city, country, zip, account_id, is_default
|
||||
"#,
|
||||
)
|
||||
.bind(msg.name)
|
||||
.bind(msg.email)
|
||||
.bind(msg.phone)
|
||||
.bind(msg.street)
|
||||
.bind(msg.city)
|
||||
.bind(msg.country)
|
||||
.bind(msg.zip)
|
||||
.bind(msg.account_id)
|
||||
.bind(msg.is_default)
|
||||
.fetch_one(pool)
|
||||
.await
|
||||
.map_err(|_| Error::CreateAccountAddress.into())
|
||||
@ -167,6 +170,7 @@ pub struct UpdateAccountAddress {
|
||||
pub id: model::AddressId,
|
||||
pub name: model::Name,
|
||||
pub email: model::Email,
|
||||
pub phone: model::Phone,
|
||||
pub street: model::Street,
|
||||
pub city: model::City,
|
||||
pub country: model::Country,
|
||||
@ -189,9 +193,9 @@ pub(crate) async fn update_account_address(
|
||||
sqlx::query_as(
|
||||
r#"
|
||||
UPDATE account_addresses
|
||||
SET name = $2, email = $3, street = $4, city = $5, country = $6, zip = $7, account_id = $8, is_default = $9
|
||||
SET name = $2, email = $3, street = $4, city = $5, country = $6, zip = $7, account_id = $8, is_default = $9, phone = $10
|
||||
WHERE id = $1
|
||||
RETURNING id, name, email, street, city, country, zip, account_id, is_default
|
||||
RETURNING id, name, email, phone, street, city, country, zip, account_id, is_default
|
||||
"#,
|
||||
)
|
||||
.bind(msg.id)
|
||||
@ -203,7 +207,140 @@ RETURNING id, name, email, street, city, country, zip, account_id, is_default
|
||||
.bind(msg.zip)
|
||||
.bind(msg.account_id)
|
||||
.bind(msg.is_default)
|
||||
.bind(msg.phone)
|
||||
.fetch_one(pool)
|
||||
.await
|
||||
.map_err(|_| Error::CreateAccountAddress.into())
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use actix::{Actor, Addr};
|
||||
use config::*;
|
||||
use fake::Fake;
|
||||
use model::*;
|
||||
|
||||
use crate::*;
|
||||
|
||||
pub struct NoOpts;
|
||||
|
||||
impl UpdateConfig for NoOpts {}
|
||||
|
||||
async fn test_create_account(db: Addr<Database>) -> FullAccount {
|
||||
let login: String = fake::faker::internet::en::Username().fake();
|
||||
let email: String = fake::faker::internet::en::FreeEmail().fake();
|
||||
let hash: String = fake::faker::internet::en::Password(10..20).fake();
|
||||
|
||||
db.send(CreateAccount {
|
||||
email: model::Email::new(email),
|
||||
login: model::Login::new(login),
|
||||
pass_hash: model::PassHash::new(hash),
|
||||
role: Role::Admin,
|
||||
})
|
||||
.await
|
||||
.unwrap()
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
#[actix::test]
|
||||
async fn full_check() {
|
||||
let config = config::default_load(&mut NoOpts);
|
||||
config
|
||||
.lock()
|
||||
.database_mut()
|
||||
.set_url("postgres://postgres@localhost/bazzar_test");
|
||||
|
||||
let db = crate::Database::build(config).await.start();
|
||||
|
||||
// account
|
||||
let account = test_create_account(db.clone()).await;
|
||||
|
||||
// address
|
||||
let mut address: AccountAddress = {
|
||||
let name: String = fake::faker::name::en::Name().fake();
|
||||
let email: String = fake::faker::internet::en::FreeEmail().fake();
|
||||
let phone: String = fake::faker::phone_number::en::PhoneNumber().fake();
|
||||
let street: String = fake::faker::address::en::StreetName().fake();
|
||||
let city: String = fake::faker::address::en::CityName().fake();
|
||||
let country: String = fake::faker::address::en::CountryName().fake();
|
||||
let zip: String = fake::faker::address::en::ZipCode().fake();
|
||||
let account_id = Some(account.id);
|
||||
let is_default: bool = fake::faker::boolean::en::Boolean(6).fake();
|
||||
|
||||
let address = db
|
||||
.send(CreateAccountAddress {
|
||||
name: model::Name::new(name.clone()),
|
||||
email: model::Email::new(email.clone()),
|
||||
phone: model::Phone::new(phone.clone()),
|
||||
street: model::Street::new(street.clone()),
|
||||
city: model::City::new(city.clone()),
|
||||
country: model::Country::new(country.clone()),
|
||||
zip: model::Zip::new(zip.clone()),
|
||||
account_id: account_id.clone(),
|
||||
is_default: is_default.clone(),
|
||||
})
|
||||
.await
|
||||
.unwrap()
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(
|
||||
address,
|
||||
model::AccountAddress {
|
||||
id: model::AddressId::new(1),
|
||||
name: model::Name::new(name.clone()),
|
||||
email: model::Email::new(email.clone()),
|
||||
phone: model::Phone::new(phone.clone()),
|
||||
street: model::Street::new(street.clone()),
|
||||
city: model::City::new(city.clone()),
|
||||
country: model::Country::new(country.clone()),
|
||||
zip: model::Zip::new(zip.clone()),
|
||||
account_id: account.id,
|
||||
is_default,
|
||||
}
|
||||
);
|
||||
address
|
||||
};
|
||||
|
||||
let found = db
|
||||
.send(FindAccountAddress {
|
||||
account_id: account.id,
|
||||
address_id: address.id,
|
||||
})
|
||||
.await
|
||||
.unwrap()
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(found, address);
|
||||
|
||||
let changed = db
|
||||
.send(UpdateAccountAddress {
|
||||
id: address.id,
|
||||
name: address.name.clone(),
|
||||
email: address.email.clone(),
|
||||
phone: address.phone.clone(),
|
||||
street: address.street.clone(),
|
||||
city: address.city.clone(),
|
||||
country: address.country.clone(),
|
||||
zip: address.zip.clone(),
|
||||
account_id: address.account_id.clone(),
|
||||
is_default: true,
|
||||
})
|
||||
.await
|
||||
.unwrap()
|
||||
.unwrap();
|
||||
|
||||
address.is_default = true;
|
||||
|
||||
assert_eq!(changed, address);
|
||||
|
||||
let default_address = db
|
||||
.send(DefaultAccountAddress {
|
||||
account_id: account.id,
|
||||
})
|
||||
.await
|
||||
.unwrap()
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(default_address, address);
|
||||
}
|
||||
}
|
||||
|
@ -196,16 +196,16 @@ impl Actor for Database {
|
||||
///
|
||||
/// ```
|
||||
/// # use database_manager::photos::Error;
|
||||
/// async fn load() {
|
||||
/// # let pool: sqlx::PgPool::connect("").await.unwrap();
|
||||
/// async fn load(pool: sqlx::PgPool) {
|
||||
/// use database_manager::MultiLoad;
|
||||
/// let t = pool.begin().await.unwrap();
|
||||
/// let mut t = pool.begin().await.unwrap();
|
||||
/// let mut multi = MultiLoad::new(
|
||||
/// &mut t,
|
||||
/// "SELECT id, name FROM products WHERE ",
|
||||
/// " id = "
|
||||
/// );
|
||||
/// multi.load(4, vec![1,2,3,4], |_| Error::All.into());
|
||||
/// let products: Vec<model::Product> = multi.load(4, vec![1, 2, 3, 4].into_iter(), |_| Error::All.into())
|
||||
/// .await.unwrap();
|
||||
/// t.commit().await.unwrap();
|
||||
/// }
|
||||
/// ```
|
||||
|
@ -78,6 +78,7 @@ impl OrderManager {
|
||||
pub struct CreateOrderAddress {
|
||||
pub name: model::Name,
|
||||
pub email: model::Email,
|
||||
pub phone: model::Phone,
|
||||
pub street: model::Street,
|
||||
pub city: model::City,
|
||||
pub country: model::Country,
|
||||
@ -130,6 +131,7 @@ pub(crate) async fn create_account_order(
|
||||
database_manager::CreateAccountAddress {
|
||||
name: input.name,
|
||||
email: input.email,
|
||||
phone: input.phone,
|
||||
street: input.street,
|
||||
city: input.city,
|
||||
country: input.country,
|
||||
|
@ -285,6 +285,7 @@ pub(crate) async fn create_order(
|
||||
api::OrderAddressInput::Address(api::CreateOrderAddress {
|
||||
name,
|
||||
email,
|
||||
phone,
|
||||
street,
|
||||
city,
|
||||
country,
|
||||
@ -292,6 +293,7 @@ pub(crate) async fn create_order(
|
||||
}) => order_manager::OrderAddressInput::Address(order_manager::CreateOrderAddress {
|
||||
name,
|
||||
email: email.clone(),
|
||||
phone,
|
||||
street,
|
||||
city,
|
||||
country,
|
||||
|
@ -51,7 +51,6 @@ async fn main() {
|
||||
|
||||
let db = database_manager::Database::build(config.clone())
|
||||
.await
|
||||
.unwrap()
|
||||
.start();
|
||||
|
||||
let res = tokio::join!(
|
||||
|
6
scripts/test.sh
Executable file
6
scripts/test.sh
Executable file
@ -0,0 +1,6 @@
|
||||
#!/usr/bin/env zsh
|
||||
|
||||
psql postgres postgres -c "DROP DATABASE bazzar_test"
|
||||
psql postgres postgres -c "CREATE DATABASE bazzar_test"
|
||||
sqlx migrate run --database-url='postgres://postgres@localhost/bazzar_test'
|
||||
cargo test
|
@ -63,6 +63,7 @@ pub struct AccountAddress {
|
||||
pub id: AddressId,
|
||||
pub name: Name,
|
||||
pub email: Email,
|
||||
pub phone: Phone,
|
||||
pub street: Street,
|
||||
pub city: City,
|
||||
pub country: Country,
|
||||
@ -77,6 +78,7 @@ impl From<crate::AccountAddress> for AccountAddress {
|
||||
id,
|
||||
name,
|
||||
email,
|
||||
phone,
|
||||
street,
|
||||
city,
|
||||
country,
|
||||
@ -89,6 +91,7 @@ impl From<crate::AccountAddress> for AccountAddress {
|
||||
id,
|
||||
name,
|
||||
email,
|
||||
phone,
|
||||
street,
|
||||
city,
|
||||
country,
|
||||
@ -502,6 +505,7 @@ pub struct SearchRequest {
|
||||
pub struct CreateOrderAddress {
|
||||
pub name: Name,
|
||||
pub email: Email,
|
||||
pub phone: Phone,
|
||||
pub street: Street,
|
||||
pub city: City,
|
||||
pub country: Country,
|
||||
|
@ -1,4 +1,5 @@
|
||||
use fake::faker::internet::en::{FreeEmail, Password as FakePass, Username};
|
||||
use fake::faker::phone_number::en::PhoneNumber;
|
||||
use fake::Fake;
|
||||
|
||||
use crate::*;
|
||||
@ -15,6 +16,12 @@ impl<T> fake::Dummy<T> for Email {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> fake::Dummy<T> for Phone {
|
||||
fn dummy_with_rng<R: Rng + ?Sized>(_config: &T, _rng: &mut R) -> Self {
|
||||
Self(PhoneNumber().fake())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> fake::Dummy<T> for ProductShortDesc {
|
||||
fn dummy_with_rng<R: Rng + ?Sized>(_config: &T, _rng: &mut R) -> Self {
|
||||
use fake::faker::lorem::en::Words;
|
||||
|
@ -342,7 +342,9 @@ impl Login {
|
||||
|
||||
#[cfg_attr(feature = "db", derive(sqlx::Type))]
|
||||
#[cfg_attr(feature = "db", sqlx(transparent))]
|
||||
#[derive(Serialize, Debug, Clone, Default, Deref, DerefMut, From, Display)]
|
||||
#[derive(
|
||||
Serialize, Debug, Clone, Default, PartialOrd, PartialEq, Deref, DerefMut, From, Display,
|
||||
)]
|
||||
#[serde(transparent)]
|
||||
pub struct Email(String);
|
||||
|
||||
@ -356,6 +358,34 @@ impl Email {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "db", derive(sqlx::Type))]
|
||||
#[cfg_attr(feature = "db", sqlx(transparent))]
|
||||
#[derive(
|
||||
Serialize,
|
||||
Deserialize,
|
||||
Debug,
|
||||
Clone,
|
||||
Default,
|
||||
PartialOrd,
|
||||
PartialEq,
|
||||
Deref,
|
||||
DerefMut,
|
||||
From,
|
||||
Display,
|
||||
)]
|
||||
#[serde(transparent)]
|
||||
pub struct Phone(String);
|
||||
|
||||
impl Phone {
|
||||
pub fn invalid_empty() -> Self {
|
||||
Self("".into())
|
||||
}
|
||||
|
||||
pub fn new<S: Into<String>>(s: S) -> Self {
|
||||
Self(s.into())
|
||||
}
|
||||
}
|
||||
|
||||
impl FromStr for Email {
|
||||
type Err = TransformError;
|
||||
|
||||
@ -680,7 +710,9 @@ impl PartialEq<PasswordConfirmation> for Password {
|
||||
#[cfg_attr(feature = "dummy", derive(fake::Dummy))]
|
||||
#[cfg_attr(feature = "db", derive(sqlx::Type))]
|
||||
#[cfg_attr(feature = "db", sqlx(transparent))]
|
||||
#[derive(Serialize, Deserialize, Copy, Clone, Debug, Deref, Display, From)]
|
||||
#[derive(
|
||||
Serialize, Deserialize, Copy, Clone, Debug, PartialOrd, PartialEq, Deref, Display, From,
|
||||
)]
|
||||
#[serde(transparent)]
|
||||
pub struct AccountId(RecordId);
|
||||
|
||||
@ -1134,12 +1166,32 @@ pub enum ShippingMethod {
|
||||
#[cfg_attr(feature = "dummy", derive(fake::Dummy))]
|
||||
#[cfg_attr(feature = "db", derive(sqlx::Type))]
|
||||
#[cfg_attr(feature = "db", sqlx(transparent))]
|
||||
#[derive(Serialize, Deserialize, Debug, Copy, Clone, Hash, Deref, Display, From)]
|
||||
#[derive(
|
||||
Serialize, Deserialize, Debug, Copy, Clone, Hash, PartialOrd, PartialEq, Deref, Display, From,
|
||||
)]
|
||||
pub struct AddressId(RecordId);
|
||||
|
||||
impl AddressId {
|
||||
pub fn new(id: RecordId) -> Self {
|
||||
Self(id)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "db", derive(sqlx::Type))]
|
||||
#[cfg_attr(feature = "db", sqlx(transparent))]
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, Default, Deref, DerefMut, From, Display)]
|
||||
#[derive(
|
||||
Serialize,
|
||||
Deserialize,
|
||||
Debug,
|
||||
Clone,
|
||||
Default,
|
||||
PartialOrd,
|
||||
PartialEq,
|
||||
Deref,
|
||||
DerefMut,
|
||||
From,
|
||||
Display,
|
||||
)]
|
||||
#[serde(transparent)]
|
||||
pub struct Name(String);
|
||||
|
||||
@ -1151,7 +1203,19 @@ impl Name {
|
||||
|
||||
#[cfg_attr(feature = "db", derive(sqlx::Type))]
|
||||
#[cfg_attr(feature = "db", sqlx(transparent))]
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, Default, Deref, DerefMut, From, Display)]
|
||||
#[derive(
|
||||
Serialize,
|
||||
Deserialize,
|
||||
Debug,
|
||||
Clone,
|
||||
Default,
|
||||
PartialOrd,
|
||||
PartialEq,
|
||||
Deref,
|
||||
DerefMut,
|
||||
From,
|
||||
Display,
|
||||
)]
|
||||
#[serde(transparent)]
|
||||
pub struct Street(String);
|
||||
|
||||
@ -1163,7 +1227,19 @@ impl Street {
|
||||
|
||||
#[cfg_attr(feature = "db", derive(sqlx::Type))]
|
||||
#[cfg_attr(feature = "db", sqlx(transparent))]
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, Default, Deref, DerefMut, From, Display)]
|
||||
#[derive(
|
||||
Serialize,
|
||||
Deserialize,
|
||||
Debug,
|
||||
Clone,
|
||||
Default,
|
||||
PartialOrd,
|
||||
PartialEq,
|
||||
Deref,
|
||||
DerefMut,
|
||||
From,
|
||||
Display,
|
||||
)]
|
||||
#[serde(transparent)]
|
||||
pub struct City(String);
|
||||
|
||||
@ -1175,7 +1251,19 @@ impl City {
|
||||
|
||||
#[cfg_attr(feature = "db", derive(sqlx::Type))]
|
||||
#[cfg_attr(feature = "db", sqlx(transparent))]
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, Default, Deref, DerefMut, From, Display)]
|
||||
#[derive(
|
||||
Serialize,
|
||||
Deserialize,
|
||||
Debug,
|
||||
Clone,
|
||||
Default,
|
||||
PartialOrd,
|
||||
PartialEq,
|
||||
Deref,
|
||||
DerefMut,
|
||||
From,
|
||||
Display,
|
||||
)]
|
||||
#[serde(transparent)]
|
||||
pub struct Country(String);
|
||||
|
||||
@ -1187,7 +1275,19 @@ impl Country {
|
||||
|
||||
#[cfg_attr(feature = "db", derive(sqlx::Type))]
|
||||
#[cfg_attr(feature = "db", sqlx(transparent))]
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, Default, Deref, DerefMut, From, Display)]
|
||||
#[derive(
|
||||
Serialize,
|
||||
Deserialize,
|
||||
Debug,
|
||||
Clone,
|
||||
Default,
|
||||
PartialOrd,
|
||||
PartialEq,
|
||||
Deref,
|
||||
DerefMut,
|
||||
From,
|
||||
Display,
|
||||
)]
|
||||
#[serde(transparent)]
|
||||
pub struct Zip(String);
|
||||
|
||||
@ -1199,11 +1299,12 @@ impl Zip {
|
||||
|
||||
#[cfg_attr(feature = "dummy", derive(fake::Dummy))]
|
||||
#[cfg_attr(feature = "db", derive(sqlx::FromRow))]
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
#[derive(Serialize, Deserialize, PartialEq, Debug)]
|
||||
pub struct AccountAddress {
|
||||
pub id: AddressId,
|
||||
pub name: Name,
|
||||
pub email: Email,
|
||||
pub phone: Phone,
|
||||
pub street: Street,
|
||||
pub city: City,
|
||||
pub country: Country,
|
||||
|
Loading…
Reference in New Issue
Block a user