mirror of
https://github.com/R0m1k3/LogiFlow.git
synced 2026-10-19 21:18:25 +02:00
Merge pull request #575 from R0m1k3/fix/weather-timestamptz
fix(rust) : lire les colonnes timestamp que la production déclare en …
This commit is contained in:
3 files changed
+163
-2
No files matched your search
@@ -178,6 +178,11 @@ async function main() {
|
||||
const attributes: string[] = [];
|
||||
const field = RUST_KEYWORDS.has(column.name) ? `${column.name}_` : column.name;
|
||||
if (field !== column.name) attributes.push(`#[sqlx(rename = "${column.name}")]`);
|
||||
// timestamp dans shared/schema.ts, mais parfois timestamptz en production
|
||||
// (tables créées hors des migrations du dépôt) : lu dans les deux cas
|
||||
if (base === "NaiveDateTime") {
|
||||
attributes.push(`#[sqlx(try_from = "${nullable ? "crate::db::AnyTimestampOpt" : "crate::db::AnyTimestamp"}")]`);
|
||||
}
|
||||
const serde = [`rename = "${column.jsKey}"`];
|
||||
if (base === "NaiveDateTime") serde.push(`serialize_with = "${nullable ? "crate::json::ts_opt" : "crate::json::ts"}"`);
|
||||
if (base === "Decimal") {
|
||||
|
||||
+96
-2
@@ -4,9 +4,11 @@
|
||||
// Comme node-pg, chaque valeur part en texte et PostgreSQL la convertit vers le
|
||||
// type de la colonne ($1::date, $2::numeric…) : mêmes conversions, mêmes erreurs.
|
||||
|
||||
use chrono::{DateTime, NaiveDateTime, Utc};
|
||||
use serde_json::Value;
|
||||
use sqlx::postgres::{PgArguments, PgRow};
|
||||
use sqlx::{Arguments, FromRow, PgPool};
|
||||
use sqlx::error::BoxDynError;
|
||||
use sqlx::postgres::{PgArguments, PgRow, PgTypeInfo, PgValueRef};
|
||||
use sqlx::{Arguments, Decode, FromRow, PgPool, Postgres, Type, ValueRef};
|
||||
|
||||
use crate::zod::Parsed;
|
||||
|
||||
@@ -34,6 +36,85 @@ pub trait Table: for<'r> FromRow<'r, PgRow> + Send + Unpin {
|
||||
}
|
||||
}
|
||||
|
||||
/// Colonne `timestamp` de shared/schema.ts, lue que la base réelle la déclare
|
||||
/// `timestamp` ou `timestamptz`. Certaines tables de production ont été créées en
|
||||
/// dehors des migrations du dépôt avec `timestamptz` (weather_settings.created_at,
|
||||
/// avoirs…), et sqlx refuse de lire un `timestamptz` en NaiveDateTime.
|
||||
///
|
||||
/// Un `timestamptz` est rendu en heure UTC : la même valeur que l'API sérialise
|
||||
/// ensuite avec crate::json::ts (« …Z »). schema.rs l'utilise par
|
||||
/// `#[sqlx(try_from = "crate::db::AnyTimestamp")]` : le champ reste NaiveDateTime.
|
||||
pub struct AnyTimestamp(pub NaiveDateTime);
|
||||
|
||||
/// AnyTimestamp d'une colonne qui peut être NULL
|
||||
pub struct AnyTimestampOpt(pub Option<NaiveDateTime>);
|
||||
|
||||
fn is_timestamptz(ty: &PgTypeInfo) -> bool {
|
||||
<DateTime<Utc> as Type<Postgres>>::compatible(ty)
|
||||
}
|
||||
|
||||
fn any_timestamp_compatible(ty: &PgTypeInfo) -> bool {
|
||||
<NaiveDateTime as Type<Postgres>>::compatible(ty) || is_timestamptz(ty)
|
||||
}
|
||||
|
||||
fn decode_any_timestamp(value: PgValueRef<'_>) -> Result<NaiveDateTime, BoxDynError> {
|
||||
let timestamptz = is_timestamptz(&value.type_info());
|
||||
if timestamptz {
|
||||
Ok(<DateTime<Utc> as Decode<'_, Postgres>>::decode(value)?.naive_utc())
|
||||
} else {
|
||||
<NaiveDateTime as Decode<'_, Postgres>>::decode(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl Type<Postgres> for AnyTimestamp {
|
||||
fn type_info() -> PgTypeInfo {
|
||||
<NaiveDateTime as Type<Postgres>>::type_info()
|
||||
}
|
||||
|
||||
fn compatible(ty: &PgTypeInfo) -> bool {
|
||||
any_timestamp_compatible(ty)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'r> Decode<'r, Postgres> for AnyTimestamp {
|
||||
fn decode(value: PgValueRef<'r>) -> Result<Self, BoxDynError> {
|
||||
decode_any_timestamp(value).map(Self)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<AnyTimestamp> for NaiveDateTime {
|
||||
fn from(value: AnyTimestamp) -> Self {
|
||||
value.0
|
||||
}
|
||||
}
|
||||
|
||||
impl Type<Postgres> for AnyTimestampOpt {
|
||||
fn type_info() -> PgTypeInfo {
|
||||
<NaiveDateTime as Type<Postgres>>::type_info()
|
||||
}
|
||||
|
||||
fn compatible(ty: &PgTypeInfo) -> bool {
|
||||
any_timestamp_compatible(ty)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'r> Decode<'r, Postgres> for AnyTimestampOpt {
|
||||
fn decode(value: PgValueRef<'r>) -> Result<Self, BoxDynError> {
|
||||
// Row::try_get ne vérifie pas le type d'une valeur NULL et la passe telle
|
||||
// quelle à decode (comme pour Option<T>)
|
||||
if value.is_null() {
|
||||
return Ok(Self(None));
|
||||
}
|
||||
decode_any_timestamp(value).map(|timestamp| Self(Some(timestamp)))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<AnyTimestampOpt> for Option<NaiveDateTime> {
|
||||
fn from(value: AnyTimestampOpt) -> Self {
|
||||
value.0
|
||||
}
|
||||
}
|
||||
|
||||
/// Valeur JavaScript telle que node-pg l'envoie (prepareValue) : texte, ou NULL
|
||||
pub fn pg_text(value: &Value) -> Option<String> {
|
||||
match value {
|
||||
@@ -263,6 +344,19 @@ mod tests {
|
||||
value.as_object().cloned().unwrap()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn horodatage_lu_en_timestamp_comme_en_timestamptz() {
|
||||
let timestamp = <NaiveDateTime as Type<Postgres>>::type_info();
|
||||
let timestamptz = <DateTime<Utc> as Type<Postgres>>::type_info();
|
||||
let date = <chrono::NaiveDate as Type<Postgres>>::type_info();
|
||||
for ty in [×tamp, ×tamptz] {
|
||||
assert!(<AnyTimestamp as Type<Postgres>>::compatible(ty));
|
||||
assert!(<AnyTimestampOpt as Type<Postgres>>::compatible(ty));
|
||||
}
|
||||
assert!(!<AnyTimestamp as Type<Postgres>>::compatible(&date));
|
||||
assert!(!<AnyTimestampOpt as Type<Postgres>>::compatible(&date));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn valeurs_comme_node_pg() {
|
||||
// Valeurs de require('pg/lib/utils').prepareValue dans Node
|
||||
|
||||
@@ -34,14 +34,18 @@ pub struct AvoirsRow {
|
||||
pub webhook_sent: Option<bool>,
|
||||
#[serde(rename = "nocodbVerified")]
|
||||
pub nocodb_verified: Option<bool>,
|
||||
#[sqlx(try_from = "crate::db::AnyTimestampOpt")]
|
||||
#[serde(rename = "nocodbVerifiedAt", serialize_with = "crate::json::ts_opt")]
|
||||
pub nocodb_verified_at: Option<NaiveDateTime>,
|
||||
#[sqlx(try_from = "crate::db::AnyTimestampOpt")]
|
||||
#[serde(rename = "processedAt", serialize_with = "crate::json::ts_opt")]
|
||||
pub processed_at: Option<NaiveDateTime>,
|
||||
#[serde(rename = "createdBy")]
|
||||
pub created_by: String,
|
||||
#[sqlx(try_from = "crate::db::AnyTimestampOpt")]
|
||||
#[serde(rename = "createdAt", serialize_with = "crate::json::ts_opt")]
|
||||
pub created_at: Option<NaiveDateTime>,
|
||||
#[sqlx(try_from = "crate::db::AnyTimestampOpt")]
|
||||
#[serde(rename = "updatedAt", serialize_with = "crate::json::ts_opt")]
|
||||
pub updated_at: Option<NaiveDateTime>,
|
||||
}
|
||||
@@ -173,8 +177,10 @@ pub struct ContactsRow {
|
||||
pub email: Option<String>,
|
||||
#[serde(rename = "notes")]
|
||||
pub notes: Option<String>,
|
||||
#[sqlx(try_from = "crate::db::AnyTimestampOpt")]
|
||||
#[serde(rename = "createdAt", serialize_with = "crate::json::ts_opt")]
|
||||
pub created_at: Option<NaiveDateTime>,
|
||||
#[sqlx(try_from = "crate::db::AnyTimestampOpt")]
|
||||
#[serde(rename = "updatedAt", serialize_with = "crate::json::ts_opt")]
|
||||
pub updated_at: Option<NaiveDateTime>,
|
||||
}
|
||||
@@ -285,6 +291,7 @@ pub struct CustomerOrdersRow {
|
||||
pub is_promotional_price: Option<bool>,
|
||||
#[serde(rename = "customerNotified")]
|
||||
pub customer_notified: Option<bool>,
|
||||
#[sqlx(try_from = "crate::db::AnyTimestampOpt")]
|
||||
#[serde(rename = "notifiedAt", serialize_with = "crate::json::ts_opt")]
|
||||
pub notified_at: Option<NaiveDateTime>,
|
||||
#[serde(rename = "notifiedComment")]
|
||||
@@ -295,8 +302,10 @@ pub struct CustomerOrdersRow {
|
||||
pub group_id: i32,
|
||||
#[serde(rename = "createdBy")]
|
||||
pub created_by: String,
|
||||
#[sqlx(try_from = "crate::db::AnyTimestampOpt")]
|
||||
#[serde(rename = "createdAt", serialize_with = "crate::json::ts_opt")]
|
||||
pub created_at: Option<NaiveDateTime>,
|
||||
#[sqlx(try_from = "crate::db::AnyTimestampOpt")]
|
||||
#[serde(rename = "updatedAt", serialize_with = "crate::json::ts_opt")]
|
||||
pub updated_at: Option<NaiveDateTime>,
|
||||
}
|
||||
@@ -458,6 +467,7 @@ pub struct DashboardMessagesRow {
|
||||
pub store_id: Option<i32>,
|
||||
#[serde(rename = "createdBy")]
|
||||
pub created_by: String,
|
||||
#[sqlx(try_from = "crate::db::AnyTimestampOpt")]
|
||||
#[serde(rename = "createdAt", serialize_with = "crate::json::ts_opt")]
|
||||
pub created_at: Option<NaiveDateTime>,
|
||||
}
|
||||
@@ -531,6 +541,7 @@ pub struct DatabaseBackupsRow {
|
||||
pub description: Option<String>,
|
||||
#[serde(rename = "size")]
|
||||
pub size: Option<i64>,
|
||||
#[sqlx(try_from = "crate::db::AnyTimestampOpt")]
|
||||
#[serde(rename = "createdAt", serialize_with = "crate::json::ts_opt")]
|
||||
pub created_at: Option<NaiveDateTime>,
|
||||
#[serde(rename = "createdBy")]
|
||||
@@ -625,6 +636,7 @@ pub struct DeliveriesRow {
|
||||
pub group_id: i32,
|
||||
#[serde(rename = "scheduledDate")]
|
||||
pub scheduled_date: NaiveDate,
|
||||
#[sqlx(try_from = "crate::db::AnyTimestampOpt")]
|
||||
#[serde(rename = "deliveredDate", serialize_with = "crate::json::ts_opt")]
|
||||
pub delivered_date: Option<NaiveDateTime>,
|
||||
#[serde(rename = "quantity")]
|
||||
@@ -648,22 +660,27 @@ pub struct DeliveriesRow {
|
||||
serialize_with = "crate::json::numeric_opt::<2, _>"
|
||||
)]
|
||||
pub invoice_amount_ttc: Option<Decimal>,
|
||||
#[sqlx(try_from = "crate::db::AnyTimestampOpt")]
|
||||
#[serde(rename = "dueDate", serialize_with = "crate::json::ts_opt")]
|
||||
pub due_date: Option<NaiveDateTime>,
|
||||
#[serde(rename = "reconciled")]
|
||||
pub reconciled: Option<bool>,
|
||||
#[sqlx(try_from = "crate::db::AnyTimestampOpt")]
|
||||
#[serde(rename = "validatedAt", serialize_with = "crate::json::ts_opt")]
|
||||
pub validated_at: Option<NaiveDateTime>,
|
||||
#[serde(rename = "controlValidated")]
|
||||
pub control_validated: Option<bool>,
|
||||
#[serde(rename = "controlValidatedBy")]
|
||||
pub control_validated_by: Option<String>,
|
||||
#[sqlx(try_from = "crate::db::AnyTimestampOpt")]
|
||||
#[serde(rename = "controlValidatedAt", serialize_with = "crate::json::ts_opt")]
|
||||
pub control_validated_at: Option<NaiveDateTime>,
|
||||
#[serde(rename = "createdBy")]
|
||||
pub created_by: String,
|
||||
#[sqlx(try_from = "crate::db::AnyTimestampOpt")]
|
||||
#[serde(rename = "createdAt", serialize_with = "crate::json::ts_opt")]
|
||||
pub created_at: Option<NaiveDateTime>,
|
||||
#[sqlx(try_from = "crate::db::AnyTimestampOpt")]
|
||||
#[serde(rename = "updatedAt", serialize_with = "crate::json::ts_opt")]
|
||||
pub updated_at: Option<NaiveDateTime>,
|
||||
}
|
||||
@@ -860,8 +877,10 @@ pub struct DlcProductsRow {
|
||||
pub stock_epuise: Option<bool>,
|
||||
#[serde(rename = "stockEpuiseBy")]
|
||||
pub stock_epuise_by: Option<String>,
|
||||
#[sqlx(try_from = "crate::db::AnyTimestampOpt")]
|
||||
#[serde(rename = "stockEpuiseAt", serialize_with = "crate::json::ts_opt")]
|
||||
pub stock_epuise_at: Option<NaiveDateTime>,
|
||||
#[sqlx(try_from = "crate::db::AnyTimestampOpt")]
|
||||
#[serde(rename = "processedAt", serialize_with = "crate::json::ts_opt")]
|
||||
pub processed_at: Option<NaiveDateTime>,
|
||||
#[serde(rename = "processedBy")]
|
||||
@@ -874,10 +893,13 @@ pub struct DlcProductsRow {
|
||||
pub created_by: String,
|
||||
#[serde(rename = "validatedBy")]
|
||||
pub validated_by: Option<String>,
|
||||
#[sqlx(try_from = "crate::db::AnyTimestampOpt")]
|
||||
#[serde(rename = "validatedAt", serialize_with = "crate::json::ts_opt")]
|
||||
pub validated_at: Option<NaiveDateTime>,
|
||||
#[sqlx(try_from = "crate::db::AnyTimestampOpt")]
|
||||
#[serde(rename = "createdAt", serialize_with = "crate::json::ts_opt")]
|
||||
pub created_at: Option<NaiveDateTime>,
|
||||
#[sqlx(try_from = "crate::db::AnyTimestampOpt")]
|
||||
#[serde(rename = "updatedAt", serialize_with = "crate::json::ts_opt")]
|
||||
pub updated_at: Option<NaiveDateTime>,
|
||||
}
|
||||
@@ -1060,10 +1082,13 @@ pub struct ExternalApiKeysRow {
|
||||
pub key_hash: String,
|
||||
#[serde(rename = "createdBy")]
|
||||
pub created_by: Option<String>,
|
||||
#[sqlx(try_from = "crate::db::AnyTimestampOpt")]
|
||||
#[serde(rename = "createdAt", serialize_with = "crate::json::ts_opt")]
|
||||
pub created_at: Option<NaiveDateTime>,
|
||||
#[sqlx(try_from = "crate::db::AnyTimestampOpt")]
|
||||
#[serde(rename = "lastUsedAt", serialize_with = "crate::json::ts_opt")]
|
||||
pub last_used_at: Option<NaiveDateTime>,
|
||||
#[sqlx(try_from = "crate::db::AnyTimestampOpt")]
|
||||
#[serde(rename = "revokedAt", serialize_with = "crate::json::ts_opt")]
|
||||
pub revoked_at: Option<NaiveDateTime>,
|
||||
}
|
||||
@@ -1182,8 +1207,10 @@ pub struct GroupsRow {
|
||||
pub smtp_sender_email: Option<String>,
|
||||
#[serde(rename = "smtpSenderName")]
|
||||
pub smtp_sender_name: Option<String>,
|
||||
#[sqlx(try_from = "crate::db::AnyTimestampOpt")]
|
||||
#[serde(rename = "createdAt", serialize_with = "crate::json::ts_opt")]
|
||||
pub created_at: Option<NaiveDateTime>,
|
||||
#[sqlx(try_from = "crate::db::AnyTimestampOpt")]
|
||||
#[serde(rename = "updatedAt", serialize_with = "crate::json::ts_opt")]
|
||||
pub updated_at: Option<NaiveDateTime>,
|
||||
}
|
||||
@@ -1384,6 +1411,7 @@ pub struct InvoiceVerificationCacheRow {
|
||||
serialize_with = "crate::json::numeric_opt::<2, _>"
|
||||
)]
|
||||
pub invoice_amount_ttc: Option<Decimal>,
|
||||
#[sqlx(try_from = "crate::db::AnyTimestampOpt")]
|
||||
#[serde(rename = "dueDate", serialize_with = "crate::json::ts_opt")]
|
||||
pub due_date: Option<NaiveDateTime>,
|
||||
#[serde(rename = "exists")]
|
||||
@@ -1398,10 +1426,13 @@ pub struct InvoiceVerificationCacheRow {
|
||||
pub api_call_time: Option<i32>,
|
||||
#[serde(rename = "isReconciled")]
|
||||
pub is_reconciled: Option<bool>,
|
||||
#[sqlx(try_from = "crate::db::AnyTimestamp")]
|
||||
#[serde(rename = "expiresAt", serialize_with = "crate::json::ts")]
|
||||
pub expires_at: NaiveDateTime,
|
||||
#[sqlx(try_from = "crate::db::AnyTimestampOpt")]
|
||||
#[serde(rename = "createdAt", serialize_with = "crate::json::ts_opt")]
|
||||
pub created_at: Option<NaiveDateTime>,
|
||||
#[sqlx(try_from = "crate::db::AnyTimestampOpt")]
|
||||
#[serde(rename = "updatedAt", serialize_with = "crate::json::ts_opt")]
|
||||
pub updated_at: Option<NaiveDateTime>,
|
||||
}
|
||||
@@ -1542,8 +1573,10 @@ pub struct NocodbConfigRow {
|
||||
pub is_active: Option<bool>,
|
||||
#[serde(rename = "createdBy")]
|
||||
pub created_by: Option<String>,
|
||||
#[sqlx(try_from = "crate::db::AnyTimestampOpt")]
|
||||
#[serde(rename = "createdAt", serialize_with = "crate::json::ts_opt")]
|
||||
pub created_at: Option<NaiveDateTime>,
|
||||
#[sqlx(try_from = "crate::db::AnyTimestampOpt")]
|
||||
#[serde(rename = "updatedAt", serialize_with = "crate::json::ts_opt")]
|
||||
pub updated_at: Option<NaiveDateTime>,
|
||||
}
|
||||
@@ -1644,8 +1677,10 @@ pub struct OrdersRow {
|
||||
pub notes: Option<String>,
|
||||
#[serde(rename = "createdBy")]
|
||||
pub created_by: String,
|
||||
#[sqlx(try_from = "crate::db::AnyTimestampOpt")]
|
||||
#[serde(rename = "createdAt", serialize_with = "crate::json::ts_opt")]
|
||||
pub created_at: Option<NaiveDateTime>,
|
||||
#[sqlx(try_from = "crate::db::AnyTimestampOpt")]
|
||||
#[serde(rename = "updatedAt", serialize_with = "crate::json::ts_opt")]
|
||||
pub updated_at: Option<NaiveDateTime>,
|
||||
}
|
||||
@@ -1748,8 +1783,10 @@ pub struct PublicitiesRow {
|
||||
pub year: i32,
|
||||
#[serde(rename = "createdBy")]
|
||||
pub created_by: String,
|
||||
#[sqlx(try_from = "crate::db::AnyTimestampOpt")]
|
||||
#[serde(rename = "createdAt", serialize_with = "crate::json::ts_opt")]
|
||||
pub created_at: Option<NaiveDateTime>,
|
||||
#[sqlx(try_from = "crate::db::AnyTimestampOpt")]
|
||||
#[serde(rename = "updatedAt", serialize_with = "crate::json::ts_opt")]
|
||||
pub updated_at: Option<NaiveDateTime>,
|
||||
}
|
||||
@@ -1872,8 +1909,10 @@ pub struct ReconciliationCommentsRow {
|
||||
pub type_: String,
|
||||
#[serde(rename = "authorId")]
|
||||
pub author_id: String,
|
||||
#[sqlx(try_from = "crate::db::AnyTimestampOpt")]
|
||||
#[serde(rename = "createdAt", serialize_with = "crate::json::ts_opt")]
|
||||
pub created_at: Option<NaiveDateTime>,
|
||||
#[sqlx(try_from = "crate::db::AnyTimestampOpt")]
|
||||
#[serde(rename = "updatedAt", serialize_with = "crate::json::ts_opt")]
|
||||
pub updated_at: Option<NaiveDateTime>,
|
||||
}
|
||||
@@ -1974,12 +2013,16 @@ pub struct SavTicketsRow {
|
||||
pub client_phone: Option<String>,
|
||||
#[serde(rename = "createdBy")]
|
||||
pub created_by: String,
|
||||
#[sqlx(try_from = "crate::db::AnyTimestampOpt")]
|
||||
#[serde(rename = "createdAt", serialize_with = "crate::json::ts_opt")]
|
||||
pub created_at: Option<NaiveDateTime>,
|
||||
#[sqlx(try_from = "crate::db::AnyTimestampOpt")]
|
||||
#[serde(rename = "updatedAt", serialize_with = "crate::json::ts_opt")]
|
||||
pub updated_at: Option<NaiveDateTime>,
|
||||
#[sqlx(try_from = "crate::db::AnyTimestampOpt")]
|
||||
#[serde(rename = "resolvedAt", serialize_with = "crate::json::ts_opt")]
|
||||
pub resolved_at: Option<NaiveDateTime>,
|
||||
#[sqlx(try_from = "crate::db::AnyTimestampOpt")]
|
||||
#[serde(rename = "closedAt", serialize_with = "crate::json::ts_opt")]
|
||||
pub closed_at: Option<NaiveDateTime>,
|
||||
}
|
||||
@@ -2123,6 +2166,7 @@ pub struct SessionsRow {
|
||||
pub sid: String,
|
||||
#[serde(rename = "sess")]
|
||||
pub sess: serde_json::Value,
|
||||
#[sqlx(try_from = "crate::db::AnyTimestamp")]
|
||||
#[serde(rename = "expire", serialize_with = "crate::json::ts")]
|
||||
pub expire: NaiveDateTime,
|
||||
}
|
||||
@@ -2187,6 +2231,7 @@ pub struct SupplierMailLogsRow {
|
||||
pub sent_by: String,
|
||||
#[serde(rename = "sentByName")]
|
||||
pub sent_by_name: Option<String>,
|
||||
#[sqlx(try_from = "crate::db::AnyTimestampOpt")]
|
||||
#[serde(rename = "createdAt", serialize_with = "crate::json::ts_opt")]
|
||||
pub created_at: Option<NaiveDateTime>,
|
||||
}
|
||||
@@ -2303,8 +2348,10 @@ pub struct SuppliersRow {
|
||||
pub has_dlc: Option<bool>,
|
||||
#[serde(rename = "paymentMethod")]
|
||||
pub payment_method: Option<String>,
|
||||
#[sqlx(try_from = "crate::db::AnyTimestampOpt")]
|
||||
#[serde(rename = "createdAt", serialize_with = "crate::json::ts_opt")]
|
||||
pub created_at: Option<NaiveDateTime>,
|
||||
#[sqlx(try_from = "crate::db::AnyTimestampOpt")]
|
||||
#[serde(rename = "updatedAt", serialize_with = "crate::json::ts_opt")]
|
||||
pub updated_at: Option<NaiveDateTime>,
|
||||
#[serde(rename = "automaticReconciliation")]
|
||||
@@ -2409,6 +2456,7 @@ pub struct TasksRow {
|
||||
pub title: String,
|
||||
#[serde(rename = "description")]
|
||||
pub description: Option<String>,
|
||||
#[sqlx(try_from = "crate::db::AnyTimestampOpt")]
|
||||
#[serde(rename = "startDate", serialize_with = "crate::json::ts_opt")]
|
||||
pub start_date: Option<NaiveDateTime>,
|
||||
#[serde(rename = "dueDate")]
|
||||
@@ -2423,12 +2471,15 @@ pub struct TasksRow {
|
||||
pub created_by: String,
|
||||
#[serde(rename = "groupId")]
|
||||
pub group_id: i32,
|
||||
#[sqlx(try_from = "crate::db::AnyTimestampOpt")]
|
||||
#[serde(rename = "completedAt", serialize_with = "crate::json::ts_opt")]
|
||||
pub completed_at: Option<NaiveDateTime>,
|
||||
#[serde(rename = "completedBy")]
|
||||
pub completed_by: Option<String>,
|
||||
#[sqlx(try_from = "crate::db::AnyTimestampOpt")]
|
||||
#[serde(rename = "createdAt", serialize_with = "crate::json::ts_opt")]
|
||||
pub created_at: Option<NaiveDateTime>,
|
||||
#[sqlx(try_from = "crate::db::AnyTimestampOpt")]
|
||||
#[serde(rename = "updatedAt", serialize_with = "crate::json::ts_opt")]
|
||||
pub updated_at: Option<NaiveDateTime>,
|
||||
}
|
||||
@@ -2539,6 +2590,7 @@ pub struct UserGroupsRow {
|
||||
pub user_id: String,
|
||||
#[serde(rename = "groupId")]
|
||||
pub group_id: i32,
|
||||
#[sqlx(try_from = "crate::db::AnyTimestampOpt")]
|
||||
#[serde(rename = "createdAt", serialize_with = "crate::json::ts_opt")]
|
||||
pub created_at: Option<NaiveDateTime>,
|
||||
}
|
||||
@@ -2599,8 +2651,10 @@ pub struct UsersRow {
|
||||
pub role: String,
|
||||
#[serde(rename = "passwordChanged")]
|
||||
pub password_changed: Option<bool>,
|
||||
#[sqlx(try_from = "crate::db::AnyTimestampOpt")]
|
||||
#[serde(rename = "createdAt", serialize_with = "crate::json::ts_opt")]
|
||||
pub created_at: Option<NaiveDateTime>,
|
||||
#[sqlx(try_from = "crate::db::AnyTimestampOpt")]
|
||||
#[serde(rename = "updatedAt", serialize_with = "crate::json::ts_opt")]
|
||||
pub updated_at: Option<NaiveDateTime>,
|
||||
}
|
||||
@@ -2701,8 +2755,10 @@ pub struct UtilitiesRow {
|
||||
pub sales_analysis_url: Option<String>,
|
||||
#[serde(rename = "automaticBackupsEnabled")]
|
||||
pub automatic_backups_enabled: Option<bool>,
|
||||
#[sqlx(try_from = "crate::db::AnyTimestampOpt")]
|
||||
#[serde(rename = "createdAt", serialize_with = "crate::json::ts_opt")]
|
||||
pub created_at: Option<NaiveDateTime>,
|
||||
#[sqlx(try_from = "crate::db::AnyTimestampOpt")]
|
||||
#[serde(rename = "updatedAt", serialize_with = "crate::json::ts_opt")]
|
||||
pub updated_at: Option<NaiveDateTime>,
|
||||
}
|
||||
@@ -2775,8 +2831,10 @@ pub struct WeatherDataRow {
|
||||
pub conditions: String,
|
||||
#[serde(rename = "isCurrentYear")]
|
||||
pub is_current_year: bool,
|
||||
#[sqlx(try_from = "crate::db::AnyTimestampOpt")]
|
||||
#[serde(rename = "createdAt", serialize_with = "crate::json::ts_opt")]
|
||||
pub created_at: Option<NaiveDateTime>,
|
||||
#[sqlx(try_from = "crate::db::AnyTimestampOpt")]
|
||||
#[serde(rename = "updatedAt", serialize_with = "crate::json::ts_opt")]
|
||||
pub updated_at: Option<NaiveDateTime>,
|
||||
}
|
||||
@@ -2867,8 +2925,10 @@ pub struct WeatherSettingsRow {
|
||||
pub location: String,
|
||||
#[serde(rename = "isActive")]
|
||||
pub is_active: bool,
|
||||
#[sqlx(try_from = "crate::db::AnyTimestampOpt")]
|
||||
#[serde(rename = "createdAt", serialize_with = "crate::json::ts_opt")]
|
||||
pub created_at: Option<NaiveDateTime>,
|
||||
#[sqlx(try_from = "crate::db::AnyTimestampOpt")]
|
||||
#[serde(rename = "updatedAt", serialize_with = "crate::json::ts_opt")]
|
||||
pub updated_at: Option<NaiveDateTime>,
|
||||
}
|
||||
@@ -2938,8 +2998,10 @@ pub struct WebhookBapConfigRow {
|
||||
pub description: Option<String>,
|
||||
#[serde(rename = "isActive")]
|
||||
pub is_active: bool,
|
||||
#[sqlx(try_from = "crate::db::AnyTimestampOpt")]
|
||||
#[serde(rename = "createdAt", serialize_with = "crate::json::ts_opt")]
|
||||
pub created_at: Option<NaiveDateTime>,
|
||||
#[sqlx(try_from = "crate::db::AnyTimestampOpt")]
|
||||
#[serde(rename = "updatedAt", serialize_with = "crate::json::ts_opt")]
|
||||
pub updated_at: Option<NaiveDateTime>,
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user