From ea5a2380f19164fe4e9b9e5c3dd9d6f3acf620b8 Mon Sep 17 00:00:00 2001 From: padreug Date: Wed, 13 Aug 2025 15:31:18 +0200 Subject: [PATCH] feat: Add market integration roadmap to NOSTR architecture documentation - Introduce a comprehensive roadmap for integrating nostr-market-app purchasing functionality into the web-app. - Outline key components of the shopping cart system, checkout process, and order management. - Detail phased implementation strategy, including enhanced user experience and advanced features. - Include security, performance, and testing considerations to ensure robust integration. feat: Enhance market store with new order and cart management features - Introduce new interfaces for Order, OrderItem, ContactInfo, and ShippingZone to support enhanced order management. - Update Stall and Product interfaces to include currency and shipping details. - Implement a comprehensive shopping cart system with stall-specific carts, including methods for adding, removing, and updating items. - Add payment-related interfaces and methods for managing payment requests and statuses. - Enhance filter options to include in-stock status and payment methods, improving product filtering capabilities. - Refactor computed properties and methods for better cart management and checkout processes. feat: Implement shopping cart functionality with new components and routing - Add ShoppingCart, CartItem, and CartSummary components to manage cart items and display summaries. - Introduce Cart.vue page to serve as the main shopping cart interface, integrating cart and summary components. - Update Navbar.vue to include a cart icon with item count, enhancing user navigation. - Implement cart management features in the market store, including item addition, quantity updates, and removal. - Establish routing for the cart page, ensuring seamless navigation for users. - Enhance ProductCard.vue to support adding items to the cart directly from the product listing. feat: Update cart and checkout functionality with improved navigation and button labels - Change "Proceed to Checkout" button text to dynamic "Place Order" based on context in CartSummary.vue. - Update "Continue Shopping" button to "Back to Cart" in CartSummary.vue for clearer navigation. - Modify routing for checkout to include stall ID in ShoppingCart.vue, enhancing checkout process. - Simplify Cart.vue by removing CartSummary component and focusing on ShoppingCart display. - Add new route for checkout with stall ID in router configuration for better handling of checkout flows. feat: Enhance cart and checkout components with improved shipping address handling - Update CartSummary.vue to use readonly types for cart items and shipping zones, ensuring immutability. - Modify Checkout.vue to conditionally display the shipping address field based on the selected shipping zone's requirements for physical shipping. - Add a digital delivery note for products that do not require a shipping address. - Introduce a computed property to determine if a shipping address is required, improving validation logic during checkout. - Update market store to include a new property for shipping zones indicating if physical shipping is required. feat: Implement order placement functionality in checkout process - Add a "Place Order" button in Checkout.vue that triggers the order placement process. - Introduce loading state during order placement to enhance user experience. - Implement createAndPlaceOrder method in market store to handle order creation and status updates. - Include error handling for order placement failures, providing user feedback on errors. - Update checkout logic to validate shipping zone and contact information before proceeding. feat: Add Order History page and update Navbar for order tracking - Introduce a new OrderHistory.vue page to display users' past orders with filtering and sorting options. - Update Navbar.vue to include an "Order History" option with a badge showing the count of orders. - Implement computed properties for order count and enhance user navigation experience. feat: Integrate Nostr functionality for order management and user notifications - Add NostrExtensionGuide component to inform users about the required Nostr extension for order transmission. - Implement useNostrOrders composable to manage Nostr connection, event creation, and order sending. - Update Checkout.vue to display Nostr connection status and provide feedback on order transmission. - Enhance OrderHistory.vue to show Nostr transmission status and details for each order. - Modify market store to handle Nostr event details and errors during order placement, ensuring local fallback. - Introduce types for Nostr events to improve type safety and integration with the existing order management system. refactor: Update Nostr relay configuration to use environment variable - Change DEFAULT_RELAYS to dynamically retrieve relay URLs from the VITE_MARKET_RELAYS environment variable. - Add error handling to ensure relays are configured before establishing a connection. - Modify createBlankEvent function to return a more precise type. - Update event signing process to ensure the event ID is generated correctly before signing. refactor: useAuth switch Enhance Nostr order management with authentication checks - Integrate user authentication checks to ensure Nostr features are only accessible to authenticated users. - Replace direct window.nostr calls with auth store methods for retrieving public and private keys. - Implement a helper function for signing events and mock encryption for order content. - Remove obsolete Nostr type definitions to streamline the codebase. feat: Enhance Checkout.vue with Nostr processing feedback and cleanup - Update the checkout button to disable based on order placement state. - Simplify order placement feedback by removing unnecessary Nostr processing checks. - Introduce a new visual indicator for Nostr order processing status. - Refactor computed properties for better clarity and efficiency in shipping zone handling. refactor: Streamline Nostr order handling and integrate buyer public key retrieval - Remove redundant Nostr relay tag from order event creation in useNostrOrders. - Update Checkout.vue to retrieve the buyer's public key from the auth store, enhancing order placement logic. - Modify createAndPlaceOrder method in market store to accept an optional Nostr orders instance for improved flexibility in order processing. refactor: Remove Nostr-related components and streamline order processing - Delete NostrExtensionGuide.vue and associated type definitions to simplify the codebase. - Remove unused useNostr.ts file and related logic from useNostrOrders.ts. - Update order handling in market store to directly integrate Nostr publishing without relying on external components. - Enhance Checkout.vue and Cart.vue to reflect changes in Nostr integration and provide clearer order status feedback. feat: Enhance Nostr chat functionality with malformed message handling - Introduce tracking for malformed message IDs to prevent repeated processing attempts. - Implement functions to mark messages as malformed, clean up old entries, and retrieve statistics on malformed messages. - Add periodic cleanup of malformed messages to manage memory usage. - Enhance message processing logic to skip previously identified malformed messages and provide detailed error handling for decryption failures. - Update the return object to include new functions for managing malformed messages. ZZ feat: Implement Lightning invoice management in market store - Add functionality to create and manage Lightning invoices for orders. - Introduce payment monitoring and status updates for invoices. - Implement payment confirmation messaging via Nostr upon successful payment. - Enhance order interface to include new fields for Lightning invoice details and payment status. ZZ feat: Enhance OrderHistory.vue with payment status indicators and invoice management - Add visual indicators for payment status, including 'Paid' and 'Payment Pending' badges. - Implement expandable payment display for orders with Lightning invoices. - Introduce functionality to toggle payment display and generate Lightning invoices. - Update order status messaging to reflect payment requirements and invoice generation status. ZZ feat: Enhance OrderHistory.vue with payment status indicators and invoice management - Add visual indicators for payment status, including 'Paid' and 'Payment Pending' badges. - Implement expandable payment display for orders with Lightning invoices. - Introduce functionality to toggle payment display and generate Lightning invoices. - Update order status messaging to reflect payment requirements and invoice generation status. feat: Implement order event handling in useOrderEvents composable - Introduce useOrderEvents composable to manage subscription and processing of order-related events. - Define order event types and interfaces for better type safety and clarity. - Implement methods to handle payment requests, order status updates, and invoice generation. - Enhance OrderHistory.vue to display order event subscription status and last update timestamp. - Update market store to include order update functionality for better integration with order events. FIX: Build errors refactor: Update component styles and improve UI consistency across market pages - Replace various color classes with updated design tokens for better consistency. - Change background colors of components to align with the new design system. - Update text colors to enhance readability and maintain a cohesive look. - Refactor class names in CartItem.vue, CartSummary.vue, DashboardOverview.vue, and other components to use the new color scheme. - Ensure all components reflect the updated design guidelines for a unified user experience. refactor: Remove Order History references from Navbar component - Eliminate order count computation and related UI elements from the Navbar. - Streamline the Navbar by removing the Order History button and badge. - Maintain existing functionality for other menu items, ensuring a cleaner user interface. feat: Implement QR code generation and download functionality in PaymentDisplay component - Add QR code generation for payment requests using the qrcode library. - Enhance UI to display loading states and error messages during QR code generation. - Introduce a download button for users to save the generated QR code. - Implement logic to regenerate QR code when the invoice changes. refactor: Replace useRelayHub with relayHubComposable across components - Update imports in multiple components and composables to use the new relayHubComposable for better consistency and maintainability. - Enhance OrderHistory.vue with debug information for development, displaying key states related to orders, authentication, and relay hub connectivity. - Remove unnecessary reconnect button from RelayHubStatus.vue to streamline user interactions. - Improve logging in useOrderEvents for better debugging and monitoring of order event subscriptions. refactor: Update OrderHistory.vue styles for improved UI consistency - Replace color classes with updated design tokens for better alignment with the new design system. - Enhance readability by adjusting text colors and background styles for payment status indicators. - Ensure a cohesive look across the component by standardizing class names and styles. refactor: Update component styles for improved UI consistency across checkout pages - Replace color classes with updated design tokens for better alignment with the new design system. - Enhance readability by adjusting text colors and background styles in CartSummary.vue, PaymentDisplay.vue, Checkout.vue, and OrderHistory.vue. - Standardize class names and styles to ensure a cohesive look across all components. feat: Implement invoice generation and Nostr integration in MerchantStore component - Add functionality to generate Lightning invoices for orders and send them to customers via Nostr. - Introduce a new sendInvoiceToCustomer method to update order details and publish invoice information. - Enhance order event handling in useOrderEvents to update existing orders with new invoice data. - Improve error handling and logging for invoice generation and sending processes. feat: Enhance MerchantStore and PaymentDisplay components for improved invoice handling - Add wallet indicator in MerchantStore to display the selected wallet name during pending orders. - Implement temporary fixes for missing buyer and seller public keys when generating invoices. - Update invoice generation logic to utilize the first available wallet and improve error handling. - Modify PaymentDisplay to use the new bolt11 field for payment requests and enhance date formatting. - Refactor order event handling to ensure accurate updates and invoice management across components. feat: Enhance order event processing in useOrderEvents composable - Refactor processOrderEvent to handle incoming Nostr market order events with improved validation and logging. - Implement logic to update existing orders or create new ones based on event data, ensuring accurate order management. - Add detailed console logging for better debugging and tracking of order events and their statuses. - Ensure compatibility with market order structure and invoice details for seamless integration with payment processing. feat: Enhance order management with localStorage persistence - Update createOrder method to optionally accept an order ID from events, improving order tracking. - Convert items from readonly to mutable for better manipulation. - Implement localStorage persistence for orders, ensuring data is saved and loaded across sessions. - Add methods to save and load orders from localStorage, enhancing user experience and data reliability. feat: Update invoice creation to support additional metadata and nostrmarket compatibility - Modify createInvoice method to accept an optional extra parameter for additional metadata. - Change invoice tag to 'nostrmarket' for improved compatibility with Nostr market. - Include merchant and buyer public keys in the invoice data for better integration. - Update invoice creation in market store to utilize new parameters for enhanced functionality. feat: Enhance order and invoice handling for Nostr market compatibility - Add originalOrderId to order events for tracking Nostr order IDs. - Update invoice creation to utilize original Nostr order ID when generating invoices. - Improve logging for invoice requests to LNBits, providing better visibility into the data being sent. - Ensure compatibility with nostrmarket by adjusting order ID handling in the market store. fix: Refine invoice creation logic for Nostr market compatibility - Adjust order ID handling in invoice creation to prioritize originalOrderId for better compatibility with nostrmarket. - Enhance logging to provide clearer insights into the order ID being used during invoice generation. feat: Integrate nostrmarket service for order publishing and merchant catalog management - Implement functionality to publish orders via the nostrmarket protocol, replacing the previous Nostr integration. - Add methods to publish merchant catalogs, including stalls and products, to nostrmarket with event ID tracking. - Enhance order interface to include nostrEventId for better integration with nostrmarket. - Improve error handling and logging for nostrmarket publishing processes. refactor: Simplify order creation logic in useOrderEvents and update contact structure in nostrmarketService - Streamline order creation by using event.id and defaulting to 'unknown' for stallId. - Update contact structure to include address and message, removing optional email and phone fields for clarity. - Ensure compatibility with new order data structure for improved integration with nostrmarket. feat: Add bech32 to hex conversion utility and integrate into nostrmarketService - Implement a new utility function to convert bech32 keys to hex format, enhancing key handling. - Update nostrmarketService to utilize the new conversion function for user public and private keys. - Modify contact structure to include additional fields for improved order information management. feat: Add nostrclient configuration to AppConfig for enhanced Nostr integration - Introduce a new nostrclient property in AppConfig to manage Nostr client settings. - Include url and enabled fields to configure the Nostr client connection dynamically. - Ensure compatibility with environment variables for flexible deployment configurations. feat: Introduce comprehensive order management and fulfillment documentation - Add ORDER_MANAGEMENT_FULFILLMENT.md to detail the complete order lifecycle, including order states, data models, and merchant/customer interfaces. - Implement test scripts for verifying order and payment request formats in test-nostrmarket-format.js. - Create PaymentRequestDialog.vue for handling payment requests with dynamic options and QR code generation. - Enhance useOrderEvents.ts to process nostrmarket protocol messages for order management. - Update nostrmarketService.ts to handle payment requests and order status updates, ensuring seamless integration with the marketplace. - Integrate payment request dialog in Market.vue and manage its state in the market store. refactor: Remove obsolete test script for nostrmarket order format - Delete test-nostrmarket-format.js as it is no longer needed for verifying order and payment request formats. - Update PaymentRequestDialog.vue to enhance UI components and integrate QR code generation for payment requests. - Refactor payment handling and notification logic to utilize toast notifications instead of Quasar's notify system. feat: Enhance OrderHistory component with payment request handling and QR code generation - Add UI elements to display payment request status and options in OrderHistory.vue. - Implement functions to copy payment requests, open Lightning wallets, and download QR codes. - Update nostrmarketService to generate QR codes for payment requests and manage order statuses effectively. - Remove obsolete PaymentRequestDialog integration from Market.vue for a cleaner UI. feat: Add debug information and toast notifications in OrderHistory component - Introduce debug info display for payment requests and hashes in OrderHistory.vue. - Implement toast notifications for actions like copying payment requests, opening wallets, and downloading QR codes. - Enhance error handling with user feedback for various order-related actions. - Remove obsolete payment request dialog methods from market store for cleaner code. feat: Revamp CartItem and ShoppingCart components for improved layout and functionality - Enhance CartItem.vue with responsive design for desktop and mobile views, including better organization of product details, price, quantity controls, and remove button. - Update ShoppingCart.vue to separate desktop and mobile layouts, improving the user experience with clearer action buttons and cart summary display. - Implement consistent styling and layout adjustments for better visual coherence across different screen sizes. --- NOSTR_ARCHITECTURE.md | 327 +++++++ ORDER_MANAGEMENT_FULFILLMENT.md | 921 ++++++++++++++++++ src/App.vue | 6 +- src/components/NostrmarketPublisher.vue | 301 ++++++ src/components/RelayHubStatus.vue | 12 +- src/components/layout/Navbar.vue | 33 +- src/components/market/CartItem.vue | 250 +++++ src/components/market/CartSummary.vue | 232 +++++ src/components/market/DashboardOverview.vue | 310 ++++++ src/components/market/MarketSettings.vue | 331 +++++++ src/components/market/MerchantStore.vue | 550 +++++++++++ src/components/market/OrderHistory.vue | 599 ++++++++++++ src/components/market/PaymentDisplay.vue | 344 +++++++ .../market/PaymentRequestDialog.vue | 287 ++++++ src/components/market/ProductCard.vue | 35 +- src/components/market/ShoppingCart.vue | 250 +++++ src/components/nostr/ChatComponent.vue | 2 +- src/components/nostr/NostrFeed.vue | 16 +- src/components/ui/LogoutConfirmDialog.vue | 2 +- .../LogoutConfirmDialog.vue | 2 +- src/composables/useMarket.ts | 36 +- src/composables/useNostrChat.ts | 138 ++- src/composables/useNostrOrders.ts | 248 +++++ src/composables/useNostrclientHub.ts | 198 ++++ src/composables/useOrderEvents.ts | 585 +++++++++++ src/composables/useRelayHub.ts | 63 +- src/lib/config/index.ts | 8 + src/lib/nostr/nostrclientHub.ts | 334 +++++++ src/lib/nostr/relayHub.ts | 33 +- src/lib/nostr/utils.ts | 18 + src/lib/notifications/manager.ts | 28 +- src/lib/services/invoiceService.ts | 189 ++++ src/lib/services/nostrmarketService.ts | 396 ++++++++ src/lib/services/paymentMonitor.ts | 275 ++++++ src/lib/utils/bech32.ts | 11 + src/pages/Cart.vue | 68 ++ src/pages/Checkout.vue | 438 +++++++++ src/pages/Market.vue | 12 +- src/pages/MarketDashboard.vue | 126 +++ src/pages/OrderHistory.vue | 425 ++++++++ src/pages/RelayHubStatus.vue | 4 +- src/router/index.ts | 30 + src/stores/market.ts | 656 ++++++++++++- 43 files changed, 8983 insertions(+), 146 deletions(-) create mode 100644 ORDER_MANAGEMENT_FULFILLMENT.md create mode 100644 src/components/NostrmarketPublisher.vue create mode 100644 src/components/market/CartItem.vue create mode 100644 src/components/market/CartSummary.vue create mode 100644 src/components/market/DashboardOverview.vue create mode 100644 src/components/market/MarketSettings.vue create mode 100644 src/components/market/MerchantStore.vue create mode 100644 src/components/market/OrderHistory.vue create mode 100644 src/components/market/PaymentDisplay.vue create mode 100644 src/components/market/PaymentRequestDialog.vue create mode 100644 src/components/market/ShoppingCart.vue create mode 100644 src/composables/useNostrOrders.ts create mode 100644 src/composables/useNostrclientHub.ts create mode 100644 src/composables/useOrderEvents.ts create mode 100644 src/lib/nostr/nostrclientHub.ts create mode 100644 src/lib/nostr/utils.ts create mode 100644 src/lib/services/invoiceService.ts create mode 100644 src/lib/services/nostrmarketService.ts create mode 100644 src/lib/services/paymentMonitor.ts create mode 100644 src/lib/utils/bech32.ts create mode 100644 src/pages/Cart.vue create mode 100644 src/pages/Checkout.vue create mode 100644 src/pages/MarketDashboard.vue create mode 100644 src/pages/OrderHistory.vue diff --git a/NOSTR_ARCHITECTURE.md b/NOSTR_ARCHITECTURE.md index 4ff0c7f..550eb22 100644 --- a/NOSTR_ARCHITECTURE.md +++ b/NOSTR_ARCHITECTURE.md @@ -780,3 +780,330 @@ This architecture makes it easy to add new Nostr functionality: 8. **Metrics and Monitoring**: Add comprehensive metrics for relay performance This architecture makes the app more maintainable, performant, and user-friendly while providing a solid foundation for future features. + +## Market Integration Roadmap + +### Overview +This document outlines the roadmap for integrating the nostr-market-app purchasing functionality into the web-app, creating a seamless e-commerce experience while maintaining the decentralized, Nostr-based architecture. + +### Analysis of nostr-market-app Purchasing Flow + +The nostr-market-app has a sophisticated purchasing system with the following key components: + +#### 1. Shopping Cart System +- **Cart Management**: Products are added to stall-specific carts +- **Cart State**: Each stall has its own cart with products and quantities +- **Cart Persistence**: Cart data is stored locally and synced across sessions + +#### 2. Checkout Process +- **Order Confirmation**: Users provide contact information (address, email, message) +- **Shipping Selection**: Multiple shipping zones with different costs +- **Payment Options**: Lightning Network, BTC Onchain, and Cashu support + +#### 3. Order Placement +- **Encrypted Communication**: Orders are encrypted using NIP-04 and sent as direct messages +- **Order Structure**: Includes product details, quantities, shipping, and contact info +- **Payment Integration**: Lightning invoice generation and QR code display + +#### 4. Key Components +- `ShoppingCartCheckout.vue` - Main checkout interface +- `useShoppingCart.js` - Cart management logic +- `useOrders.js` - Order placement and management +- `marketStore.js` - Central state management + +### Implementation Roadmap + +#### Phase 1: Enhanced Shopping Cart System (High Priority) + +**1.1 Extend Market Store** +- Add cart management with stall-specific carts +- Implement cart persistence and synchronization +- Add shipping zone support +- Extend existing `useMarketStore` with cart functionality + +**1.2 Create Cart Components** +- `ShoppingCart.vue` - Cart overview and management +- `CartItem.vue` - Individual cart item with quantity controls +- `CartSummary.vue` - Cart totals and checkout button +- Integrate cart icon in header with item count + +**1.3 Cart State Management** +- Implement stall-specific cart structure +- Add cart persistence to local storage +- Sync cart state across components +- Handle cart updates and real-time synchronization + +#### Phase 2: Checkout System (High Priority) + +**2.1 Checkout Flow** +- `CheckoutPage.vue` - Main checkout interface +- Contact information form (address, email, message) +- Shipping zone selection with cost calculation +- Order summary and confirmation + +**2.2 Payment Integration** +- Lightning Network invoice generation +- QR code display for payments +- Payment status tracking +- Integration with existing payment infrastructure + +**2.3 Checkout State Management** +- Form validation and error handling +- Multi-step checkout process +- Order confirmation and review + +#### Phase 3: Order Management (Medium Priority) + +**3.1 Order Processing** +- Encrypted order creation using NIP-04 +- Direct message sending to merchants +- Order status tracking and updates +- Integration with existing Nostr messaging system + +**3.2 Order History** +- `OrdersPage.vue` - User's order history +- Order status updates and notifications +- Communication with merchants +- Order filtering and search + +**3.3 Order Communication** +- Encrypted messaging between buyers and sellers +- Order status notifications +- Shipping updates and tracking + +#### Phase 4: Enhanced User Experience (Medium Priority) + +**4.1 Streamlined Navigation** +- Integrated cart icon in header +- Quick checkout from product cards +- Seamless flow between browsing and purchasing +- Breadcrumb navigation for checkout process + +**4.2 Real-time Updates** +- Live inventory updates +- Order status notifications +- Chat integration with merchants +- WebSocket connections for live updates + +#### Phase 5: Advanced Features (Low Priority) + +**5.1 Multiple Payment Methods** +- BTC Onchain payments +- Cashu integration +- Payment method selection +- Payment preference storage + +**5.2 Advanced Filtering and Search** +- Enhanced product search +- Advanced filtering options +- Saved search preferences +- Product recommendations + +**5.3 Merchant Tools** +- Merchant dashboard +- Inventory management +- Order fulfillment tools +- Analytics and reporting + +### Technical Implementation Details + +#### State Management Architecture + +**Extended Market Store Structure** +```typescript +interface CartItem { + product: Product + quantity: number + stallId: string +} + +interface StallCart { + id: string + merchant: string + products: CartItem[] + subtotal: number + shippingZone?: ShippingZone +} + +interface Order { + id: string + cartId: string + status: OrderStatus + contactInfo: ContactInfo + shippingZone: ShippingZone + paymentRequest?: string + createdAt: number + updatedAt: number +} +``` + +#### Component Architecture + +**New Components to Create** +1. `ShoppingCart.vue` - Main cart interface +2. `CartItem.vue` - Individual cart item +3. `CartSummary.vue` - Cart totals and checkout +4. `CheckoutPage.vue` - Complete checkout flow +5. `OrderSummary.vue` - Order review and confirmation +6. `PaymentModal.vue` - Payment processing interface +7. `OrdersPage.vue` - Order history and management + +**Enhanced Existing Components** +1. `ProductCard.vue` - Add quick add to cart +2. `Market.vue` - Integrate cart functionality +3. Header navigation - Add cart icon and count + +#### Data Flow + +**Cart Management Flow** +1. User adds product to cart +2. Cart state updated in store +3. Cart persisted to local storage +4. Cart UI components updated +5. Real-time sync across components + +**Checkout Flow** +1. User initiates checkout from cart +2. Contact information collected +3. Shipping zone selected +4. Order summary displayed +5. Payment method selected +6. Order encrypted and sent +7. Payment processed +8. Order confirmed + +#### Integration Points + +**Existing Systems** +1. **Authentication**: Integrate with existing auth system +2. **Nostr Store**: Extend existing Nostr functionality +3. **Relay Hub**: Use existing relay connections +4. **Notifications**: Leverage existing notification system +5. **Storage**: Extend existing storage mechanisms + +**New Systems** +1. **Payment Gateway**: Lightning Network integration +2. **Order Management**: Encrypted order processing +3. **Cart Persistence**: Local storage with sync +4. **Real-time Updates**: WebSocket connections + +### Security Considerations + +#### Data Encryption +- All order data encrypted using NIP-04 +- Private keys never stored in plain text +- Secure communication channels +- Payment information protection + +#### Privacy Protection +- Minimal data collection +- User consent for data sharing +- Anonymity options for users +- Secure storage practices + +#### Payment Security +- Lightning Network security +- Payment verification +- Fraud prevention measures +- Secure key management + +### Performance Considerations + +#### Optimization Strategies +- Lazy loading of cart components +- Efficient state management +- Minimal re-renders +- Optimized storage operations + +#### Scalability +- Modular component architecture +- Efficient data structures +- Caching strategies +- Performance monitoring + +### Testing Strategy + +#### Unit Testing +- Component functionality +- Store actions and mutations +- Utility functions +- Integration points + +#### Integration Testing +- End-to-end checkout flow +- Payment processing +- Order management +- Real-time updates + +#### User Testing +- Usability testing +- Performance testing +- Security testing +- Accessibility testing + +### Deployment and Rollout + +#### Phase 1 Deployment +- Enhanced shopping cart +- Basic checkout functionality +- Order placement system + +#### Phase 2 Deployment +- Payment integration +- Order tracking +- Enhanced user experience + +#### Phase 3 Deployment +- Advanced features +- Performance optimizations +- Full feature set + +### Success Metrics + +#### User Experience Metrics +- Cart abandonment rate +- Checkout completion rate +- Time to complete purchase +- User satisfaction scores + +#### Technical Metrics +- Page load times +- Cart sync performance +- Order processing speed +- Error rates + +#### Business Metrics +- Conversion rates +- Average order value +- Repeat purchase rate +- Customer retention + +### Future Enhancements + +#### Long-term Vision +- Multi-currency support +- Advanced analytics +- AI-powered recommendations +- Mobile app development +- API for third-party integrations + +#### Scalability Plans +- Microservices architecture +- Distributed storage +- Global relay network +- Cross-platform support + +### Conclusion + +This roadmap provides a comprehensive plan for integrating the nostr-market-app purchasing functionality into the web-app. The phased approach ensures core functionality is delivered first while building toward a full-featured e-commerce platform. + +The integration will maintain the decentralized, Nostr-based architecture while providing a professional, user-friendly shopping experience. Each phase builds upon the previous one, ensuring a smooth development process and consistent user experience. + +Key success factors include: +- Maintaining the existing architecture and design patterns +- Ensuring seamless integration with current systems +- Prioritizing user experience and performance +- Implementing robust security measures +- Creating a scalable and maintainable codebase + +This roadmap serves as a living document that should be updated as development progresses and new requirements emerge. diff --git a/ORDER_MANAGEMENT_FULFILLMENT.md b/ORDER_MANAGEMENT_FULFILLMENT.md new file mode 100644 index 0000000..af79620 --- /dev/null +++ b/ORDER_MANAGEMENT_FULFILLMENT.md @@ -0,0 +1,921 @@ +# Order Management & Fulfillment Workflows + +This document provides comprehensive coverage of the complete order lifecycle, from initial placement through payment processing to final fulfillment and shipping management. It includes detailed analysis of both merchant and customer interfaces, database operations, and automated fulfillment processes. + +## Overview: Order Lifecycle Management + +The marketplace implements a **comprehensive order management system** with dual interfaces for merchants and customers, supporting complete order tracking from placement to fulfillment with automated inventory management and payment processing. + +### Order States and Transitions + +```mermaid +graph LR + A[Order Created] --> B[Invoice Generated] + B --> C[Payment Request Sent] + C --> D{Payment Status} + D -->|Paid| E[Payment Confirmed] + D -->|Unpaid| F[Invoice Expired/Reissued] + F --> C + E --> G[Inventory Updated] + G --> H{Fulfillment} + H -->|Ready| I[Shipped Status] + H -->|Issue| J[Error/Refund] + I --> K[Order Complete] +``` + +## Core Order Data Models + +### 1. Order Schema (`models.py:400-485`) + +#### Order Structure Hierarchy +```python +class OrderItem(BaseModel): + product_id: str # Product identifier from order + quantity: int # Quantity ordered + +class OrderContact(BaseModel): + nostr: Optional[str] = None # Customer's nostr pubkey + phone: Optional[str] = None # Customer phone number + email: Optional[str] = None # Customer email address + +class OrderExtra(BaseModel): + products: List[ProductOverview] # Snapshot of products at time of order + currency: str # Pricing currency (USD, EUR, sat, etc.) + btc_price: str # Exchange rate at time of order + shipping_cost: float = 0 # Shipping cost in currency + shipping_cost_sat: float = 0 # Shipping cost in satoshis + fail_message: Optional[str] = None # Error message if order failed +``` + +#### Complete Order Model +```python +class Order(PartialOrder): + stall_id: str # Associated stall identifier + invoice_id: str # Lightning invoice payment hash + total: float # Total amount in satoshis + paid: bool = False # Payment status + shipped: bool = False # Shipping/fulfillment status + time: Optional[int] = None # Completion timestamp + extra: OrderExtra # Additional order metadata +``` + +### 2. Order Status Models (`models.py:467-485`) + +#### Status Update Structure +```python +class OrderStatusUpdate(BaseModel): + id: str # Order identifier + message: Optional[str] = None # Status update message + paid: Optional[bool] = False # Payment status + shipped: Optional[bool] = None # Shipping status + +class OrderReissue(BaseModel): + id: str # Order identifier to reissue + shipping_id: Optional[str] = None # Updated shipping zone + +class PaymentRequest(BaseModel): + id: str # Order identifier + message: Optional[str] = None # Response message + payment_options: List[PaymentOption] # Available payment methods +``` + +### 3. Database Schema (`migrations.py:110-130`) + +#### Order Table Structure +```sql +CREATE TABLE nostrmarket.orders ( + merchant_id TEXT NOT NULL, -- Merchant who owns this order + id TEXT PRIMARY KEY, -- Unique order identifier (UUID) + event_id TEXT, -- Nostr event ID for order placement + event_created_at INTEGER NOT NULL, -- Unix timestamp of order creation + public_key TEXT NOT NULL, -- Customer's public key + merchant_public_key TEXT NOT NULL, -- Merchant's public key + contact_data TEXT NOT NULL DEFAULT '{}', -- JSON contact information + extra_data TEXT NOT NULL DEFAULT '{}', -- JSON extra metadata + order_items TEXT NOT NULL, -- JSON array of ordered items + address TEXT, -- Shipping address (deprecated) + total REAL NOT NULL, -- Total amount in satoshis + shipping_id TEXT NOT NULL, -- Shipping zone identifier + stall_id TEXT NOT NULL, -- Associated stall identifier + invoice_id TEXT NOT NULL, -- Lightning invoice payment hash + paid BOOLEAN NOT NULL DEFAULT false, -- Payment confirmation + shipped BOOLEAN NOT NULL DEFAULT false, -- Fulfillment status + time INTEGER -- Completion timestamp +); +``` + +## Merchant Order Management Interface + +### 1. Order List Component (`order-list.js`) + +#### Component Structure and Properties +```javascript +window.app.component('order-list', { + name: 'order-list', + props: ['stall-id', 'customer-pubkey-filter', 'adminkey', 'inkey'], + template: '#order-list', + delimiters: ['${', '}'], +``` + +#### Advanced Search and Filtering (`order-list.js:15-49`) +```javascript +data: function () { + return { + orders: [], + selectedOrder: null, + search: { + publicKey: null, // Filter by customer public key + isPaid: {label: 'All', id: null}, // Payment status filter + isShipped: {label: 'All', id: null}, // Shipping status filter + }, + ternaryOptions: [ + {label: 'All', id: null}, // Show all orders + {label: 'Yes', id: 'true'}, // Filter for paid/shipped = true + {label: 'No', id: 'false'} // Filter for paid/shipped = false + ] + } +} +``` + +#### Dynamic Order Fetching (`order-list.js:156-181`) +```javascript +getOrders: async function () { + try { + // Support both stall-specific and merchant-wide queries + const ordersPath = this.stallId + ? `stall/order/${this.stallId}` // Orders for specific stall + : 'order' // All orders for merchant + + // Build query parameters for filtering + const query = [] + if (this.search.publicKey) { + query.push(`pubkey=${this.search.publicKey}`) + } + if (this.search.isPaid.id) { + query.push(`paid=${this.search.isPaid.id}`) + } + if (this.search.isShipped.id) { + query.push(`shipped=${this.search.isShipped.id}`) + } + + const {data} = await LNbits.api.request( + 'GET', + `/nostrmarket/api/v1/${ordersPath}?${query.join('&')}`, + this.inkey + ) + this.orders = data.map(s => ({...s, expanded: false})) + } catch (error) { + LNbits.utils.notifyApiError(error) + } +} +``` + +### 2. Order Display and Calculations (`order-list.js:119-155`) + +#### Product Information Retrieval +```javascript +productName: function (order, productId) { + product = order.extra.products.find(p => p.id === productId) + if (product) { + return product.name + } + return '' +}, + +productPrice: function (order, productId) { + product = order.extra.products.find(p => p.id === productId) + if (product) { + return `${product.price} ${order.extra.currency}` + } + return '' +}, + +orderTotal: function (order) { + // Calculate total from individual product costs + shipping + const productCost = order.items.reduce((t, item) => { + product = order.extra.products.find(p => p.id === item.product_id) + return t + item.quantity * product.price + }, 0) + return productCost + order.extra.shipping_cost +} +``` + +### 3. Shipping Status Management (`order-list.js:259-280`) + +#### Shipping Status Updates +```javascript +updateOrderShipped: async function () { + this.selectedOrder.shipped = !this.selectedOrder.shipped + try { + await LNbits.api.request( + 'PATCH', + `/nostrmarket/api/v1/order/${this.selectedOrder.id}`, + this.adminkey, + { + id: this.selectedOrder.id, + message: this.shippingMessage, // Custom message to customer + shipped: this.selectedOrder.shipped // New shipping status + } + ) + this.$q.notify({ + type: 'positive', + message: 'Order updated!' + }) + } catch (error) { + LNbits.utils.notifyApiError(error) + } + this.showShipDialog = false +} +``` + +#### Shipping Dialog Interface (`order-list.js:356-365`) +```javascript +showShipOrderDialog: function (order) { + this.selectedOrder = order + this.shippingMessage = order.shipped + ? 'The order has been shipped!' + : 'The order has NOT yet been shipped!' + + // Toggle status (will be confirmed on dialog submit) + this.selectedOrder.shipped = !order.shipped + this.showShipDialog = true +} +``` + +### 4. Order Recovery and Restoration (`order-list.js:194-233`) + +#### Individual Order Restoration +```javascript +restoreOrder: async function (eventId) { + try { + this.search.restoring = true + const {data} = await LNbits.api.request( + 'PUT', + `/nostrmarket/api/v1/order/restore/${eventId}`, // Restore from DM event + this.adminkey + ) + await this.getOrders() // Refresh order list + this.$q.notify({ + type: 'positive', + message: 'Order restored!' + }) + return data + } catch (error) { + LNbits.utils.notifyApiError(error) + } finally { + this.search.restoring = false + } +} +``` + +#### Bulk Order Restoration +```javascript +restoreOrders: async function () { + try { + this.search.restoring = true + await LNbits.api.request( + 'PUT', + `/nostrmarket/api/v1/orders/restore`, // Restore all from DMs + this.adminkey + ) + await this.getOrders() + this.$q.notify({ + type: 'positive', + message: 'Orders restored!' + }) + } catch (error) { + LNbits.utils.notifyApiError(error) + } +} +``` + +### 5. Invoice Management (`order-list.js:234-258`) + +#### Invoice Reissuance +```javascript +reissueOrderInvoice: async function (order) { + try { + const {data} = await LNbits.api.request( + 'PUT', + `/nostrmarket/api/v1/order/reissue`, + this.adminkey, + { + id: order.id, + shipping_id: order.shipping_id // Optional shipping zone update + } + ) + this.$q.notify({ + type: 'positive', + message: 'Order invoice reissued!' + }) + + // Update order in local state + data.expanded = order.expanded + const i = this.orders.map(o => o.id).indexOf(order.id) + if (i !== -1) { + this.orders[i] = {...this.orders[i], ...data} + } + } catch (error) { + LNbits.utils.notifyApiError(error) + } +} +``` + +## Customer Order Interface + +### 1. Customer Orders Component (`CustomerOrders.vue`) + +#### Order Display Structure +```vue +
+ + + + :pubkey="merchant.pubkey" + :profiles="profiles" + > + + + +
+ + + +
+
+
+
+``` + +### 2. Order Data Enrichment (`CustomerOrders.vue:208-220`) + +#### Order Enhancement Pipeline +```javascript +enrichOrder: function (order) { + const stall = this.stallForOrder(order); + return { + ...order, + stallName: stall?.name || "Stall", // Stall name for display + shippingZone: stall?.shipping?.find( // Shipping zone details + (s) => s.id === order.shipping_id + ) || { id: order.shipping_id, name: order.shipping_id }, + invoice: this.invoiceForOrder(order), // Parsed Lightning invoice + products: this.getProductsForOrder(order), // Product details with quantities + }; +} +``` + +#### Stall Association (`CustomerOrders.vue:221-233`) +```javascript +stallForOrder: function (order) { + try { + const productId = order.items && order.items[0]?.product_id; + if (!productId) return; + + const product = this.products.find((p) => p.id === productId); + if (!product) return; + + const stall = this.stalls.find((s) => s.id === product.stall_id); + if (!stall) return; + + return stall; + } catch (error) { + console.log(error); + } +} +``` + +### 3. Invoice Processing (`CustomerOrders.vue:234-244`) + +#### Lightning Invoice Decoding +```javascript +invoiceForOrder: function (order) { + try { + const lnPaymentOption = order?.payment_options?.find( + (p) => p.type === "ln" // Find Lightning payment option + ); + if (!lnPaymentOption?.link) return; + + return decode(lnPaymentOption.link); // Decode BOLT11 invoice + } catch (error) { + console.warn(error); + } +} +``` + +### 4. Product Aggregation (`CustomerOrders.vue:246-259`) + +#### Order Item Processing +```javascript +getProductsForOrder: function (order) { + if (!order?.items?.length) return []; + + return order.items.map((i) => { + const product = this.products.find((p) => p.id === i.product_id) || { + id: i.product_id, + name: i.product_id, // Fallback if product not found + }; + return { + ...product, + orderedQuantity: i.quantity, // Add ordered quantity to product + }; + }); +} +``` + +## Backend Order Operations + +### 1. Order Creation (`services.py:84-133`) + +#### Order Build Pipeline +```python +async def build_order_with_payment(merchant_id, merchant_public_key, data): + # 1. Validate products and calculate costs + products = await get_products_by_ids(merchant_id, [p.product_id for p in data.items]) + data.validate_order_items(products) # Ensure products exist and have stock + + shipping_zone = await get_zone(merchant_id, data.shipping_id) + product_cost_sat, shipping_cost_sat = await data.costs_in_sats( + products, shipping_zone.id, shipping_zone.cost + ) + + # 2. Check inventory availability + success, _, message = await compute_products_new_quantity( + merchant_id, [i.product_id for i in data.items], data.items + ) + if not success: + raise ValueError(message) # Insufficient inventory + + # 3. Create Lightning invoice via LNbits + payment = await create_invoice( + wallet_id=wallet_id, + amount=round(product_cost_sat + shipping_cost_sat), + memo=f"Order '{data.id}' for pubkey '{data.public_key}'", + extra={ + "tag": "nostrmarket", # Tags invoice as marketplace + "order_id": data.id, + "merchant_pubkey": merchant_public_key, + }, + ) + + # 4. Create order record + order = Order( + **data.dict(), + stall_id=products[0].stall_id, + invoice_id=payment.payment_hash, + total=product_cost_sat + shipping_cost_sat, + extra=extra, + ) + + return order, payment.bolt11, receipt +``` + +### 2. Order Retrieval API (`views_api.py:540-577`) + +#### Multi-filter Order Queries +```python +@nostrmarket_ext.get("/api/v1/stall/order/{stall_id}") +async def api_get_orders_for_stall( + stall_id: str, + paid: Optional[bool] = None, # Filter by payment status + shipped: Optional[bool] = None, # Filter by shipping status + pubkey: Optional[str] = None, # Filter by customer pubkey + wallet: WalletTypeInfo = Depends(require_invoice_key), +) -> List[Order]: + try: + merchant = await get_merchant_for_user(wallet.wallet.user) + assert merchant, "Merchant cannot be found" + + orders = await get_orders_for_stall( + merchant.id, stall_id, paid=paid, shipped=shipped, public_key=pubkey + ) + return orders + except AssertionError as ex: + raise HTTPException( + status_code=HTTPStatus.NOT_FOUND, detail=str(ex) + ) from ex +``` + +### 3. Order Status Updates (`views_api.py:625-641`) + +#### Shipping Status API +```python +@nostrmarket_ext.patch("/api/v1/order/{order_id}") +async def api_update_order_status( + data: OrderStatusUpdate, + wallet: WalletTypeInfo = Depends(require_admin_key), +) -> Order: + try: + assert data.shipped is not None, "Shipped value is required for order" + merchant = await get_merchant_for_user(wallet.wallet.user) + assert merchant, "Merchant cannot be found for order {data.id}" + + # Update shipping status in database + order = await update_order_shipped_status(merchant.id, data.id, data.shipped) + assert order, "Cannot find updated order" + + # Send status update to customer via DM + data.paid = order.paid # Include current payment status + dm_content = json.dumps( + {"type": DirectMessageType.ORDER_PAID_OR_SHIPPED.value, **data.dict()}, + separators=(",", ":"), + ensure_ascii=False, + ) + await reply_to_structured_dm( + merchant, order.public_key, DirectMessageType.ORDER_PAID_OR_SHIPPED.value, dm_content + ) + + return order + except AssertionError as ex: + raise HTTPException( + status_code=HTTPStatus.NOT_FOUND, detail=str(ex) + ) from ex +``` + +### 4. Invoice Reissuance (`views_api.py:710-740`) + +#### Payment Request Regeneration +```python +@nostrmarket_ext.put("/api/v1/order/reissue") +async def api_reissue_order_invoice( + reissue_data: OrderReissue, + wallet: WalletTypeInfo = Depends(require_admin_key), +) -> Order: + try: + merchant = await get_merchant_for_user(wallet.wallet.user) + assert merchant, "Merchant cannot be found" + + # Get existing order + data = await get_order(merchant.id, reissue_data.id) + assert data, "Order cannot be found" + + # Update shipping zone if provided + if reissue_data.shipping_id: + data.shipping_id = reissue_data.shipping_id + + # Generate new payment request + payment_req, order = await build_order_with_payment( + merchant.id, merchant.public_key, data + ) + + # Update order with new invoice details + order_update = { + "total": payment_req.total, + "invoice_id": order.invoice_id, # New payment hash + "extra_data": json.dumps(order.extra.dict()), + } + + await update_order( + merchant.id, + order.id, + **order_update, + ) + + # Send new payment request to customer + payment_req = PaymentRequest( + id=order.id, + message="Updated payment request", + payment_options=[PaymentOption(type="ln", link=order.bolt11)], + ) + + dm_content = json.dumps( + {"type": DirectMessageType.PAYMENT_REQUEST.value, **payment_req.dict()}, + ) + await reply_to_structured_dm( + merchant, order.public_key, DirectMessageType.PAYMENT_REQUEST.value, dm_content + ) + + return await get_order(merchant.id, reissue_data.id) + except Exception as ex: + logger.warning(ex) + raise HTTPException( + status_code=HTTPStatus.INTERNAL_SERVER_ERROR, + detail="Cannot reissue order invoice", + ) from ex +``` + +## Order Restoration System + +### 1. Order Recovery from Direct Messages (`services.py:645-690`) + +#### DM-based Order Restoration +```python +async def create_or_update_order_from_dm( + merchant_id: str, merchant_pubkey: str, dm: DirectMessage +): + type_, json_data = PartialDirectMessage.parse_message(dm.message) + if not json_data or "id" not in json_data: + return + + if type_ == DirectMessageType.CUSTOMER_ORDER: + # Restore customer order from DM + order, _ = await extract_customer_order_from_dm( + merchant_id, merchant_pubkey, dm, json_data + ) + new_order = await create_order(merchant_id, order) + + # Handle stall association updates + if new_order.stall_id == "None" and order.stall_id != "None": + await update_order( + merchant_id, + order.id, + **{ + "stall_id": order.stall_id, + "extra_data": json.dumps(order.extra.dict()), + }, + ) + return + + if type_ == DirectMessageType.PAYMENT_REQUEST: + # Update order with payment request details + payment_request = PaymentRequest(**json_data) + pr = payment_request.payment_options[0].link + invoice = decode(pr) + total = invoice.amount_msat / 1000 if invoice.amount_msat else 0 + await update_order( + merchant_id, + payment_request.id, + **{"total": total, "invoice_id": invoice.payment_hash}, + ) + return + + if type_ == DirectMessageType.ORDER_PAID_OR_SHIPPED: + # Update order status from status messages + order_update = OrderStatusUpdate(**json_data) + if order_update.paid: + await update_order_paid_status(order_update.id, True) + if order_update.shipped: + await update_order_shipped_status(merchant_id, order_update.id, True) +``` + +### 2. Bulk Restoration API (`views_api.py:580-595`) + +#### Complete Order Recovery +```python +@nostrmarket_ext.put("/api/v1/orders/restore") +async def api_restore_orders_from_dms( + wallet: WalletTypeInfo = Depends(require_admin_key), +): + try: + merchant = await get_merchant_for_user(wallet.wallet.user) + assert merchant, "Merchant cannot be found" + + # Get all order-related direct messages + dms = await get_orders_from_direct_messages(merchant.id) + for dm in dms: + try: + # Attempt to restore/update each order from DM history + await create_or_update_order_from_dm( + merchant.id, merchant.public_key, dm + ) + except Exception as e: + logger.debug( + f"Failed to restore order from event '{dm.event_id}': '{e!s}'." + ) + continue + + return {"status": "Orders restoration completed!"} + except AssertionError as ex: + raise HTTPException( + status_code=HTTPStatus.NOT_FOUND, detail=str(ex) + ) from ex +``` + +## Real-time Order Updates + +### 1. WebSocket Order Notifications (`order-list.js:281-296`) + +#### Live Order Addition +```javascript +addOrder: async function (data) { + if ( + !this.search.publicKey || + this.search.publicKey === data.customerPubkey // Filter matches current view + ) { + const orderData = JSON.parse(data.dm.message) + const i = this.orders.map(o => o.id).indexOf(orderData.id) + if (i === -1) { // Prevent duplicates + const order = await this.getOrder(orderData.id) // Fetch complete order data + this.orders.unshift(order) // Add to top of list + } + } +} +``` + +### 2. Payment Status Updates (`order-list.js:391-396`) + +#### Real-time Payment Confirmation +```javascript +orderPaid: function (orderId) { + const order = this.orders.find(o => o.id === orderId) + if (order) { + order.paid = true // Update payment status immediately + } +} +``` + +## Advanced Order Management Features + +### 1. Order Selection and Deep Linking (`order-list.js:294-315`) + +#### Order Detail Navigation +```javascript +orderSelected: async function (orderId, eventId) { + const order = await this.getOrder(orderId) + if (!order) { + // Order missing - offer restoration from DM + LNbits.utils + .confirmDialog( + 'Order could not be found. Do you want to restore it from this direct message?' + ) + .onOk(async () => { + const restoredOrder = await this.restoreOrder(eventId) + if (restoredOrder) { + restoredOrder.expanded = true + restoredOrder.isNew = false + this.orders = [restoredOrder] // Show only restored order + } + }) + return + } + + // Show order details + order.expanded = true + order.isNew = false + this.orders = [order] // Focus on single order +} +``` + +### 2. Customer Association and Filtering + +#### Customer Management Integration +```javascript +computed: { + customerOptions: function () { + const options = this.customers.map(c => ({ + label: this.buildCustomerLabel(c), // Include unread message counts + value: c.public_key + })) + options.unshift({label: 'All', value: null, id: null}) // All customers option + return options + } +} +``` + +### 3. Shipping Zone Integration (`order-list.js:348-355`) + +#### Dynamic Shipping Options +```javascript +getStallZones: function (stallId) { + const stall = this.stalls.find(s => s.id === stallId) + if (!stall) return [] + + return this.zoneOptions.filter(z => + stall.shipping_zones.find(s => s.id === z.id) // Only zones supported by stall + ) +} +``` + +## Database Operations + +### 1. Order CRUD Operations (`crud.py`) + +#### Order Creation +```python +async def create_order(merchant_id: str, o: Order) -> Order: + await db.execute( + """ + INSERT INTO nostrmarket.orders ( + merchant_id, id, event_id, event_created_at, public_key, + merchant_public_key, contact_data, extra_data, order_items, + address, total, shipping_id, stall_id, invoice_id, paid, shipped + ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) + """, + ( + merchant_id, o.id, o.event_id, o.event_created_at, o.public_key, + o.merchant_public_key, json.dumps(o.contact.dict()), + json.dumps(o.extra.dict()), json.dumps([i.dict() for i in o.items]), + o.address, o.total, o.shipping_id, o.stall_id, o.invoice_id, + o.paid, o.shipped, + ), + ) + return o +``` + +#### Flexible Order Queries +```python +async def get_orders(merchant_id: str, **kwargs) -> List[Order]: + # Build dynamic WHERE clause from keyword arguments + q = " AND ".join( + [ + f"{field[0]} = :{field[0]}" + for field in kwargs.items() + if field[1] is not None + ] + ) + + rows: list[dict] = await db.fetchall( + f"SELECT * FROM nostrmarket.orders WHERE merchant_id = :merchant_id " + f"{' AND ' + q if q else ''} ORDER BY event_created_at DESC", + {"merchant_id": merchant_id, **kwargs}, + ) + return [Order.from_row(row) for row in rows] +``` + +### 2. Status Update Operations + +#### Payment Status Updates +```python +async def update_order_paid_status(order_id: str, paid: bool) -> Optional[Order]: + await db.execute( + "UPDATE nostrmarket.orders SET paid = :paid WHERE id = :id", + {"paid": paid, "id": order_id}, + ) + row: dict = await db.fetchone( + "SELECT * FROM nostrmarket.orders WHERE id = :id", {"id": order_id} + ) + return Order.from_row(row) if row else None +``` + +#### Shipping Status Updates +```python +async def update_order_shipped_status( + merchant_id: str, order_id: str, shipped: bool +) -> Optional[Order]: + await db.execute( + """ + UPDATE nostrmarket.orders + SET shipped = :shipped + WHERE merchant_id = :merchant_id AND id = :id + """, + {"shipped": shipped, "merchant_id": merchant_id, "id": order_id}, + ) + row: dict = await db.fetchone( + "SELECT * FROM nostrmarket.orders WHERE merchant_id = :merchant_id AND id = :id", + {"merchant_id": merchant_id, "id": order_id}, + ) + return Order.from_row(row) if row else None +``` + +## Error Handling and Edge Cases + +### 1. Order Restoration Failures +- **Missing Products**: Orders reference products that no longer exist +- **Invalid Stall Association**: Product moved between stalls after order creation +- **Corrupted DM Data**: JSON parsing errors in message restoration +- **Payment Hash Conflicts**: Duplicate invoice IDs from reissuance + +### 2. Payment Processing Issues +- **Invoice Expiration**: Lightning invoices expire after timeout +- **Partial Payments**: Underpayment or overpayment scenarios +- **Payment Verification**: Webhook delays or failures +- **Double Payment**: Multiple payments for same order + +### 3. Inventory Synchronization +- **Race Conditions**: Multiple orders for limited stock +- **Negative Inventory**: Orders processed despite insufficient stock +- **Product Updates**: Price or availability changes after order placement +- **Stall Deactivation**: Orders for disabled stalls or products + +## Integration Points + +### 1. Payment System Integration +- **LNbits Invoice Creation**: Automatic Lightning invoice generation +- **Payment Monitoring**: Real-time payment confirmation via webhooks +- **Refund Processing**: Automated refunds for failed orders +- **Multi-currency Support**: Fiat pricing with BTC conversion + +### 2. Inventory Management Integration +- **Stock Validation**: Pre-order inventory checking +- **Automatic Deduction**: Post-payment inventory updates +- **Backorder Handling**: Out-of-stock order management +- **Restock Notifications**: Customer alerts for inventory replenishment + +### 3. Communication System Integration +- **Status Updates**: Automated customer notifications +- **Order Confirmations**: Receipt and tracking information +- **Shipping Notifications**: Fulfillment status updates +- **Support Integration**: Customer service ticket creation + +This comprehensive order management system provides complete lifecycle tracking from initial order placement through final fulfillment, with robust error handling, real-time updates, and flexible merchant tools for efficient order processing and customer communication. \ No newline at end of file diff --git a/src/App.vue b/src/App.vue index 649bfd9..9832863 100644 --- a/src/App.vue +++ b/src/App.vue @@ -6,10 +6,10 @@ import Footer from '@/components/layout/Footer.vue' import LoginDialog from '@/components/auth/LoginDialog.vue' import { Toaster } from '@/components/ui/sonner' import 'vue-sonner/style.css' -import { auth } from '@/composables/useAuth' import { useMarketPreloader } from '@/composables/useMarketPreloader' import { nostrChat } from '@/composables/useNostrChat' -import { useRelayHub } from '@/composables/useRelayHub' +import { auth } from '@/composables/useAuth' +import { relayHubComposable } from '@/composables/useRelayHub' import { toast } from 'vue-sonner' const route = useRoute() @@ -19,7 +19,7 @@ const showLoginDialog = ref(false) const marketPreloader = useMarketPreloader() // Initialize relay hub -const relayHub = useRelayHub() +const relayHub = relayHubComposable // Hide navbar on login page const showNavbar = computed(() => { diff --git a/src/components/NostrmarketPublisher.vue b/src/components/NostrmarketPublisher.vue new file mode 100644 index 0000000..3740b9b --- /dev/null +++ b/src/components/NostrmarketPublisher.vue @@ -0,0 +1,301 @@ + + + + + diff --git a/src/components/RelayHubStatus.vue b/src/components/RelayHubStatus.vue index 1ee5bb1..8222440 100644 --- a/src/components/RelayHubStatus.vue +++ b/src/components/RelayHubStatus.vue @@ -43,15 +43,12 @@
- -
@@ -65,7 +62,7 @@