From 9bdf91e71735cdb1f065a207df94a73eb7aa6dca Mon Sep 17 00:00:00 2001 From: Priec Date: Sat, 27 Jun 2026 18:03:02 +0200 Subject: [PATCH] api for packeta required to enable it --- assets/i18n/en/main.ftl | 1 + assets/i18n/sk/main.ftl | 1 + assets/views/admin/shipping/index.html | 11 ++++++++- src/controllers/admin_shipping.rs | 16 ++++++++++++- src/controllers/checkout.rs | 12 ++++++++-- src/initializers/shipping_seeder.rs | 4 ++-- src/shared/mod.rs | 1 + src/shared/shipping.rs | 31 ++++++++++++++++++++++++++ 8 files changed, 71 insertions(+), 6 deletions(-) create mode 100644 src/shared/shipping.rs diff --git a/assets/i18n/en/main.ftl b/assets/i18n/en/main.ftl index 9608403..b6ad1f2 100644 --- a/assets/i18n/en/main.ftl +++ b/assets/i18n/en/main.ftl @@ -484,6 +484,7 @@ bank-variable-symbol = Variable symbol bank-amount = Amount admin-shipping = Shipping admin-shipping-desc = set the price and availability of each delivery option. +shipping-packeta-missing-settings = Packeta can be enabled after PACKETA_API_KEY, PACKETA_API_PASSWORD and PACKETA_SENDER_LABEL are configured. admin-payments = Payments admin-payments-desc = enable or disable payment methods and edit bank-transfer details. payment-methods = Payment methods diff --git a/assets/i18n/sk/main.ftl b/assets/i18n/sk/main.ftl index d75b178..c7ddc22 100644 --- a/assets/i18n/sk/main.ftl +++ b/assets/i18n/sk/main.ftl @@ -484,6 +484,7 @@ bank-variable-symbol = Variabilný symbol bank-amount = Suma admin-shipping = Doprava admin-shipping-desc = nastaviť cenu a dostupnosť jednotlivých možností dopravy. +shipping-packeta-missing-settings = Packeta sa dá zapnúť až po nastavení PACKETA_API_KEY, PACKETA_API_PASSWORD a PACKETA_SENDER_LABEL. admin-payments = Platby admin-payments-desc = zapnite alebo vypnite spôsoby platby a upravte údaje pre prevod na účet. payment-methods = Spôsoby platby diff --git a/assets/views/admin/shipping/index.html b/assets/views/admin/shipping/index.html index 1fad714..f58df4b 100644 --- a/assets/views/admin/shipping/index.html +++ b/assets/views/admin/shipping/index.html @@ -18,12 +18,21 @@

{{ method.name }}

{{ method.carrier | upper }}{% if method.requires_pickup_point %} · {{ t(key="checkout-pickup-point", lang=lang | default(value='sk')) }}{% endif %}

+ {% if method.packeta_not_ready %} +

{{ t(key=method.lock_reason, lang=lang | default(value='sk')) }}

+ {% endif %}
{{ ui::input(name="price", id="price-" ~ method.id, value=method.price, width="w-28", attrs='inputmode="decimal"') }}
-
{{ ui::checkbox(name="enabled", label=t(key="shipping-enabled", lang=lang | default(value='sk')), checked=method.enabled) }}
+
+ {% if method.locked %} + {{ ui::checkbox(name="enabled", label=t(key="shipping-enabled", lang=lang | default(value='sk')), checked=method.enabled, attrs='disabled') }} + {% else %} + {{ ui::checkbox(name="enabled", label=t(key="shipping-enabled", lang=lang | default(value='sk')), checked=method.enabled) }} + {% endif %} +
{{ ui::button(label=t(key="save", lang=lang | default(value='sk')), type="submit", extra="ml-auto") }} {% endfor %} diff --git a/src/controllers/admin_shipping.rs b/src/controllers/admin_shipping.rs index ba7b387..7a9f7e6 100644 --- a/src/controllers/admin_shipping.rs +++ b/src/controllers/admin_shipping.rs @@ -16,6 +16,7 @@ use crate::{ shared::{ guard, money::{format_price, parse_price_to_cents}, + shipping as shipping_rules, }, }; @@ -37,13 +38,17 @@ async fn index( State(ctx): State, ) -> Result { guard::current_admin(auth, &ctx).await?; + shipping_rules::disable_packeta_if_unconfigured(&ctx).await?; let methods = shipping_methods::Entity::find() .order_by_asc(shipping_methods::Column::Position) .all(&ctx.db) .await?; + let packeta_ready = shipping_rules::packeta_ready(&ctx); let rows: Vec = methods .iter() .map(|m| { + let packeta_not_ready = m.carrier == "packeta" && !packeta_ready; + let locked = packeta_not_ready && !m.enabled; json!({ "id": m.id, "code": m.code, @@ -52,6 +57,9 @@ async fn index( "carrier": m.carrier, "requires_pickup_point": m.requires_pickup_point, "enabled": m.enabled, + "packeta_not_ready": packeta_not_ready, + "locked": locked, + "lock_reason": if packeta_not_ready { Some("shipping-packeta-missing-settings") } else { None::<&str> }, }) }) .collect(); @@ -74,9 +82,15 @@ async fn update( .one(&ctx.db) .await? .ok_or_else(|| Error::NotFound)?; + let requested_enabled = is_checked(&form.enabled); + if requested_enabled && method.carrier == "packeta" && !shipping_rules::packeta_ready(&ctx) { + return Err(Error::BadRequest( + "Packeta cannot be enabled until PACKETA_API_KEY, PACKETA_API_PASSWORD and PACKETA_SENDER_LABEL are configured.".to_string(), + )); + } let mut active = method.into_active_model(); active.price_cents = Set(parse_price_to_cents(&form.price)?); - active.enabled = Set(is_checked(&form.enabled)); + active.enabled = Set(requested_enabled); active.update(&ctx.db).await?; format::redirect("/admin/shipping") } diff --git a/src/controllers/checkout.rs b/src/controllers/checkout.rs index 142a7c1..828ffbf 100644 --- a/src/controllers/checkout.rs +++ b/src/controllers/checkout.rs @@ -18,7 +18,7 @@ use crate::{ users::{self, normalize_account_type}, }, controllers::i18n::current_lang, - shared::{currency::Currency, guard, money::format_price, settings}, + shared::{currency::Currency, guard, money::format_price, settings, shipping as shipping_rules}, views::checkout as view, }; @@ -67,11 +67,16 @@ fn cleared_cart_cookie() -> Cookie<'static> { } async fn enabled_shipping_methods(ctx: &AppContext) -> Result> { + shipping_rules::disable_packeta_if_unconfigured(ctx).await?; + let packeta_ready = shipping_rules::packeta_ready(ctx); Ok(shipping_methods::Entity::find() .filter(shipping_methods::Column::Enabled.eq(true)) .order_by_asc(shipping_methods::Column::Position) .all(&ctx.db) - .await?) + .await? + .into_iter() + .filter(|method| method.carrier != "packeta" || packeta_ready) + .collect()) } async fn enabled_payment_methods(ctx: &AppContext) -> Result> { @@ -264,6 +269,9 @@ async fn place_order( .one(&ctx.db) .await? .ok_or_else(|| Error::BadRequest("invalid shipping method".to_string()))?; + if method.carrier == "packeta" && !shipping_rules::packeta_ready(&ctx) { + return Err(Error::BadRequest("invalid shipping method".to_string())); + } let (pickup_point_id, pickup_point_name) = if method.requires_pickup_point { let id = form diff --git a/src/initializers/shipping_seeder.rs b/src/initializers/shipping_seeder.rs index d1dfa5c..4ec3cbe 100644 --- a/src/initializers/shipping_seeder.rs +++ b/src/initializers/shipping_seeder.rs @@ -9,7 +9,7 @@ use async_trait::async_trait; use loco_rs::prelude::*; use sea_orm::{ActiveModelTrait, ColumnTrait, EntityTrait, PaginatorTrait, QueryFilter, Set}; -use crate::models::shipping_methods; +use crate::{models::shipping_methods, shared::shipping as shipping_rules}; /// `(code, name, carrier, requires_pickup_point, default_price_cents, position)` const BUILTINS: [(&str, &str, &str, bool, i64, i32); 2] = [ @@ -49,6 +49,6 @@ impl Initializer for ShippingSeeder { .await?; tracing::info!(carrier = code, "seeded built-in delivery option"); } - Ok(()) + shipping_rules::disable_packeta_if_unconfigured(ctx).await } } diff --git a/src/shared/mod.rs b/src/shared/mod.rs index addac79..3d35aeb 100644 --- a/src/shared/mod.rs +++ b/src/shared/mod.rs @@ -7,4 +7,5 @@ pub mod money; pub mod pricing; pub mod rbac; pub mod settings; +pub mod shipping; pub mod slug; diff --git a/src/shared/shipping.rs b/src/shared/shipping.rs new file mode 100644 index 0000000..2518936 --- /dev/null +++ b/src/shared/shipping.rs @@ -0,0 +1,31 @@ +use loco_rs::prelude::*; +use sea_orm::{ActiveModelTrait, ColumnTrait, EntityTrait, IntoActiveModel, QueryFilter, Set}; + +use crate::{ + models::shipping_methods, + shared::settings, +}; + +pub fn packeta_ready(ctx: &AppContext) -> bool { + ["packeta_api_key", "packeta_api_password", "packeta_sender_label"] + .iter() + .all(|key| settings::get(ctx, key).is_some_and(|value| !value.trim().is_empty())) +} + +pub async fn disable_packeta_if_unconfigured(ctx: &AppContext) -> Result<()> { + if packeta_ready(ctx) { + return Ok(()); + } + let Some(method) = shipping_methods::Entity::find() + .filter(shipping_methods::Column::Carrier.eq("packeta")) + .filter(shipping_methods::Column::Enabled.eq(true)) + .one(&ctx.db) + .await? + else { + return Ok(()); + }; + let mut active = method.into_active_model(); + active.enabled = Set(false); + active.update(&ctx.db).await?; + Ok(()) +}