Create invoice table
This commit is contained in:
parent
423eec0a2c
commit
084e0064be
6 changed files with 166 additions and 0 deletions
10
migrations/V0030__invoice.sql
Normal file
10
migrations/V0030__invoice.sql
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
CREATE TABLE invoice (
|
||||||
|
id UUID PRIMARY KEY,
|
||||||
|
sender_id UUID NOT NULL REFERENCES actor_profile (id) ON DELETE CASCADE,
|
||||||
|
recipient_id UUID NOT NULL REFERENCES user_account (id) ON DELETE CASCADE,
|
||||||
|
chain_id VARCHAR(50) NOT NULL,
|
||||||
|
payment_address VARCHAR(200) NOT NULL,
|
||||||
|
invoice_status SMALLINT NOT NULL DEFAULT 1,
|
||||||
|
created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
UNIQUE (chain_id, payment_address)
|
||||||
|
);
|
|
@ -136,6 +136,17 @@ CREATE TABLE timeline_marker (
|
||||||
UNIQUE (user_id, timeline)
|
UNIQUE (user_id, timeline)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
CREATE TABLE invoice (
|
||||||
|
id UUID PRIMARY KEY,
|
||||||
|
sender_id UUID NOT NULL REFERENCES actor_profile (id) ON DELETE CASCADE,
|
||||||
|
recipient_id UUID NOT NULL REFERENCES user_account (id) ON DELETE CASCADE,
|
||||||
|
chain_id VARCHAR(50) NOT NULL,
|
||||||
|
payment_address VARCHAR(200) NOT NULL,
|
||||||
|
invoice_status SMALLINT NOT NULL DEFAULT 1,
|
||||||
|
created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
UNIQUE (chain_id, payment_address)
|
||||||
|
);
|
||||||
|
|
||||||
CREATE TABLE subscription (
|
CREATE TABLE subscription (
|
||||||
id INTEGER GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
|
id INTEGER GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
|
||||||
sender_id UUID NOT NULL REFERENCES actor_profile (id) ON DELETE CASCADE,
|
sender_id UUID NOT NULL REFERENCES actor_profile (id) ON DELETE CASCADE,
|
||||||
|
|
2
src/models/invoices/mod.rs
Normal file
2
src/models/invoices/mod.rs
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
pub mod queries;
|
||||||
|
mod types;
|
87
src/models/invoices/queries.rs
Normal file
87
src/models/invoices/queries.rs
Normal file
|
@ -0,0 +1,87 @@
|
||||||
|
use tokio_postgres::GenericClient;
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
use crate::database::catch_unique_violation;
|
||||||
|
use crate::errors::DatabaseError;
|
||||||
|
use crate::utils::caip2::ChainId;
|
||||||
|
use crate::utils::id::new_uuid;
|
||||||
|
use super::types::DbInvoice;
|
||||||
|
|
||||||
|
pub async fn create_invoice(
|
||||||
|
db_client: &impl GenericClient,
|
||||||
|
sender_id: &Uuid,
|
||||||
|
recipient_id: &Uuid,
|
||||||
|
chain_id: &ChainId,
|
||||||
|
payment_address: &str,
|
||||||
|
) -> Result<DbInvoice, DatabaseError> {
|
||||||
|
let invoice_id = new_uuid();
|
||||||
|
let row = db_client.query_one(
|
||||||
|
"
|
||||||
|
INSERT INTO invoice (
|
||||||
|
id,
|
||||||
|
sender_id,
|
||||||
|
recipient_id,
|
||||||
|
chain_id,
|
||||||
|
payment_address
|
||||||
|
)
|
||||||
|
VALUES ($1, $2, $3, $4, $5)
|
||||||
|
RETURNING invoice
|
||||||
|
",
|
||||||
|
&[
|
||||||
|
&invoice_id,
|
||||||
|
&sender_id,
|
||||||
|
&recipient_id,
|
||||||
|
&chain_id,
|
||||||
|
&payment_address,
|
||||||
|
],
|
||||||
|
).await.map_err(catch_unique_violation("invoice"))?;
|
||||||
|
let invoice = row.try_get("invoice")?;
|
||||||
|
Ok(invoice)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use serial_test::serial;
|
||||||
|
use crate::database::test_utils::create_test_database;
|
||||||
|
use crate::models::{
|
||||||
|
invoices::types::InvoiceStatus,
|
||||||
|
profiles::queries::create_profile,
|
||||||
|
profiles::types::ProfileCreateData,
|
||||||
|
users::queries::create_user,
|
||||||
|
users::types::UserCreateData,
|
||||||
|
};
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
#[serial]
|
||||||
|
async fn test_create_invoice() {
|
||||||
|
let db_client = &mut create_test_database().await;
|
||||||
|
let sender_data = ProfileCreateData {
|
||||||
|
username: "sender".to_string(),
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
let sender = create_profile(db_client, sender_data).await.unwrap();
|
||||||
|
let recipient_data = UserCreateData {
|
||||||
|
username: "recipient".to_string(),
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
let recipient = create_user(db_client, recipient_data).await.unwrap();
|
||||||
|
let chain_id = ChainId {
|
||||||
|
namespace: "monero".to_string(),
|
||||||
|
reference: "mainnet".to_string(),
|
||||||
|
};
|
||||||
|
let payment_address = "8MxABajuo71BZya9";
|
||||||
|
let invoice = create_invoice(
|
||||||
|
db_client,
|
||||||
|
&sender.id,
|
||||||
|
&recipient.id,
|
||||||
|
&chain_id,
|
||||||
|
payment_address,
|
||||||
|
).await.unwrap();
|
||||||
|
assert_eq!(invoice.sender_id, sender.id);
|
||||||
|
assert_eq!(invoice.recipient_id, recipient.id);
|
||||||
|
assert_eq!(invoice.chain_id, chain_id);
|
||||||
|
assert_eq!(invoice.payment_address, payment_address);
|
||||||
|
assert!(matches!(invoice.invoice_status, InvoiceStatus::Open));
|
||||||
|
}
|
||||||
|
}
|
55
src/models/invoices/types.rs
Normal file
55
src/models/invoices/types.rs
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
use std::convert::TryFrom;
|
||||||
|
|
||||||
|
use chrono::{DateTime, Utc};
|
||||||
|
use postgres_types::FromSql;
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
use crate::database::int_enum::{int_enum_from_sql, int_enum_to_sql};
|
||||||
|
use crate::errors::ConversionError;
|
||||||
|
use crate::utils::caip2::ChainId;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum InvoiceStatus {
|
||||||
|
Open,
|
||||||
|
Paid,
|
||||||
|
Forwarded,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<&InvoiceStatus> for i16 {
|
||||||
|
fn from(value: &InvoiceStatus) -> i16 {
|
||||||
|
match value {
|
||||||
|
InvoiceStatus::Open => 1,
|
||||||
|
InvoiceStatus::Paid => 2,
|
||||||
|
InvoiceStatus::Forwarded => 3,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<i16> for InvoiceStatus {
|
||||||
|
type Error = ConversionError;
|
||||||
|
|
||||||
|
fn try_from(value: i16) -> Result<Self, Self::Error> {
|
||||||
|
let invoice_status = match value {
|
||||||
|
1 => Self::Open,
|
||||||
|
2 => Self::Paid,
|
||||||
|
3 => Self::Forwarded,
|
||||||
|
_ => return Err(ConversionError),
|
||||||
|
};
|
||||||
|
Ok(invoice_status)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int_enum_from_sql!(InvoiceStatus);
|
||||||
|
int_enum_to_sql!(InvoiceStatus);
|
||||||
|
|
||||||
|
#[derive(FromSql)]
|
||||||
|
#[postgres(name = "invoice")]
|
||||||
|
pub struct DbInvoice {
|
||||||
|
pub id: Uuid,
|
||||||
|
pub sender_id: Uuid,
|
||||||
|
pub recipient_id: Uuid,
|
||||||
|
pub chain_id: ChainId,
|
||||||
|
pub payment_address: String,
|
||||||
|
pub invoice_status: InvoiceStatus,
|
||||||
|
pub created_at: DateTime<Utc>,
|
||||||
|
}
|
|
@ -1,5 +1,6 @@
|
||||||
pub mod attachments;
|
pub mod attachments;
|
||||||
pub mod cleanup;
|
pub mod cleanup;
|
||||||
|
pub mod invoices;
|
||||||
pub mod markers;
|
pub mod markers;
|
||||||
pub mod notifications;
|
pub mod notifications;
|
||||||
pub mod oauth;
|
pub mod oauth;
|
||||||
|
|
Loading…
Reference in a new issue