backbone-pos 0.7.1

Point of sale — cashier session, ticket + multi-tender; orchestrates billing (revenue) + payment (settlement), posts no GL directly
Documentation
//! DTOs (Data Transfer Objects)
//!
//! Generated by metaphor-schema. Do not edit manually.
//!
//! This module provides DTOs for the presentation layer,
//! with validation and OpenAPI schema support.

pub mod pos_closing_entry_dto;
pub mod pos_invoice_dto;
pub mod pos_invoice_item_dto;
pub mod pos_payment_dto;
pub mod pos_profile_dto;
pub mod pos_opening_entry_dto;
pub mod pos_cash_movement_dto;
pub mod pos_discount_dto;
pub mod pos_manager_pin_dto;
pub mod pos_floor_plan_dto;
pub mod pos_table_dto;

// Re-exports
pub use pos_closing_entry_dto::{
    CreatePosClosingEntryDto,
    UpdatePosClosingEntryDto,
    PatchPosClosingEntryDto,
    PosClosingEntryResponseDto,
    PosClosingEntryListResponseDto,
    PosClosingEntrySummaryDto,
};
pub use pos_invoice_dto::{
    CreatePosInvoiceDto,
    UpdatePosInvoiceDto,
    PatchPosInvoiceDto,
    PosInvoiceResponseDto,
    PosInvoiceListResponseDto,
    PosInvoiceSummaryDto,
};
pub use pos_invoice_item_dto::{
    CreatePosInvoiceItemDto,
    UpdatePosInvoiceItemDto,
    PatchPosInvoiceItemDto,
    PosInvoiceItemResponseDto,
    PosInvoiceItemListResponseDto,
    PosInvoiceItemSummaryDto,
};
pub use pos_payment_dto::{
    CreatePosPaymentDto,
    UpdatePosPaymentDto,
    PatchPosPaymentDto,
    PosPaymentResponseDto,
    PosPaymentListResponseDto,
    PosPaymentSummaryDto,
};
pub use pos_profile_dto::{
    CreatePosProfileDto,
    UpdatePosProfileDto,
    PatchPosProfileDto,
    PosProfileResponseDto,
    PosProfileListResponseDto,
    PosProfileSummaryDto,
};
pub use pos_opening_entry_dto::{
    CreatePosOpeningEntryDto,
    UpdatePosOpeningEntryDto,
    PatchPosOpeningEntryDto,
    PosOpeningEntryResponseDto,
    PosOpeningEntryListResponseDto,
    PosOpeningEntrySummaryDto,
};
pub use pos_cash_movement_dto::{
    CreatePosCashMovementDto,
    UpdatePosCashMovementDto,
    PatchPosCashMovementDto,
    PosCashMovementResponseDto,
    PosCashMovementListResponseDto,
    PosCashMovementSummaryDto,
};
pub use pos_discount_dto::{
    CreatePosDiscountDto,
    UpdatePosDiscountDto,
    PatchPosDiscountDto,
    PosDiscountResponseDto,
    PosDiscountListResponseDto,
    PosDiscountSummaryDto,
};
pub use pos_manager_pin_dto::{
    CreatePosManagerPinDto,
    UpdatePosManagerPinDto,
    PatchPosManagerPinDto,
    PosManagerPinResponseDto,
    PosManagerPinListResponseDto,
    PosManagerPinSummaryDto,
};
pub use pos_floor_plan_dto::{
    CreatePosFloorPlanDto,
    UpdatePosFloorPlanDto,
    PatchPosFloorPlanDto,
    PosFloorPlanResponseDto,
    PosFloorPlanListResponseDto,
    PosFloorPlanSummaryDto,
};
pub use pos_table_dto::{
    CreatePosTableDto,
    UpdatePosTableDto,
    PatchPosTableDto,
    PosTableResponseDto,
    PosTableListResponseDto,
    PosTableSummaryDto,
};

// Common pagination types
use serde::Serialize;

#[cfg(feature = "openapi")]
#[cfg(feature = "openapi")]
use utoipa::ToSchema;

/// Pagination parameters for list requests
#[derive(Debug, Clone, Default, serde::Deserialize)]
#[cfg_attr(feature = "openapi", derive(ToSchema))]
pub struct PaginationParams {
    /// Page number (1-indexed)
    #[serde(default = "default_page")]
    pub page: u32,
    /// Items per page
    #[serde(default = "default_per_page")]
    pub per_page: u32,
    /// Field to sort by
    pub sort_by: Option<String>,
    /// Sort order (asc/desc)
    pub sort_order: Option<String>,
}

fn default_page() -> u32 { 1 }
fn default_per_page() -> u32 { 20 }

/// API response wrapper
#[derive(Debug, Clone, Serialize)]
#[cfg_attr(feature = "openapi", derive(ToSchema))]
#[serde(rename_all = "camelCase")]
pub struct ApiResponse<T> {
    pub success: bool,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub data: Option<T>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub error: Option<ApiError>,
}

#[derive(Debug, Clone, Serialize)]
#[cfg_attr(feature = "openapi", derive(ToSchema))]
pub struct ApiError {
    pub code: String,
    pub message: String,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub details: Option<serde_json::Value>,
}

impl<T> ApiResponse<T> {
    pub fn ok(data: T) -> Self {
        Self { success: true, data: Some(data), error: None }
    }

    pub fn err(code: impl Into<String>, message: impl Into<String>) -> Self {
        Self {
            success: false,
            data: None,
            error: Some(ApiError {
                code: code.into(),
                message: message.into(),
                details: None,
            }),
        }
    }
}