Source Code

(define-constant contract-owner tx-sender)
(define-constant err-owner-only (err u100))
(define-constant err-not-found (err u101))
(define-constant err-unauthorized (err u102))
(define-constant err-already-exists (err u103))
(define-constant err-invalid-amount (err u104))
(define-constant err-subscription-expired (err u105))

(define-data-var account-nonce uint u0)
(define-data-var lead-nonce uint u0)

(define-map customer-accounts
  uint
  {
    organization: principal,
    subscription-tier: (string-ascii 20),
    monthly-fee: uint,
    seats: uint,
    active: bool,
    subscription-end: uint
  }
)

(define-map sales-leads
  uint
  {
    account-id: uint,
    lead-data-hash: (buff 32),
    status: (string-ascii 20),
    created-at: uint,
    assigned-to: (optional principal),
    conversion-value: uint,
    converted: bool
  }
)

(define-map ai-interactions
  {account-id: uint, interaction-id: uint}
  {
    interaction-type: (string-ascii 30),
    data-hash: (buff 32),
    timestamp: uint,
    ai-model-used: (string-ascii 30)
  }
)

(define-map org-accounts principal (list 20 uint))
(define-map account-leads uint (list 500 uint))

(define-public (create-account (subscription-tier (string-ascii 20)) (monthly-fee uint) (seats uint) (duration-blocks uint))
  (let
    (
      (account-id (+ (var-get account-nonce) u1))
      (total-cost (* monthly-fee (/ duration-blocks u4320)))
    )
    (asserts! (> monthly-fee u0) err-invalid-amount)
    (asserts! (> seats u0) err-invalid-amount)
    (try! (stx-transfer? total-cost tx-sender (as-contract tx-sender)))
    (map-set customer-accounts account-id
      {
        organization: tx-sender,
        subscription-tier: subscription-tier,
        monthly-fee: monthly-fee,
        seats: seats,
        active: true,
        subscription-end: (+ stacks-block-height duration-blocks)
      }
    )
    (map-set org-accounts tx-sender
      (unwrap-panic (as-max-len? (append (default-to (list) (map-get? org-accounts tx-sender)) account-id) u20)))
    (var-set account-nonce account-id)
    (ok account-id)
  )
)

(define-public (create-lead (account-id uint) (lead-data-hash (buff 32)))
  (let
    (
      (account (unwrap! (map-get? customer-accounts account-id) err-not-found))
      (lead-id (+ (var-get lead-nonce) u1))
    )
    (asserts! (is-eq tx-sender (get organization account)) err-unauthorized)
    (asserts! (get active account) err-subscription-expired)
    (asserts! (< stacks-block-height (get subscription-end account)) err-subscription-expired)
    (map-set sales-leads lead-id
      {
        account-id: account-id,
        lead-data-hash: lead-data-hash,
        status: "new",
        created-at: stacks-block-height,
        assigned-to: none,
        conversion-value: u0,
        converted: false
      }
    )
    (map-set account-leads account-id
      (unwrap-panic (as-max-len? (append (default-to (list) (map-get? account-leads account-id)) lead-id) u500)))
    (var-set lead-nonce lead-id)
    (ok lead-id)
  )
)

(define-public (update-lead-status (lead-id uint) (new-status (string-ascii 20)))
  (let
    (
      (lead (unwrap! (map-get? sales-leads lead-id) err-not-found))
      (account (unwrap! (map-get? customer-accounts (get account-id lead)) err-not-found))
    )
    (asserts! (is-eq tx-sender (get organization account)) err-unauthorized)
    (map-set sales-leads lead-id (merge lead {status: new-status}))
    (ok true)
  )
)

(define-public (convert-lead (lead-id uint) (conversion-value uint))
  (let
    (
      (lead (unwrap! (map-get? sales-leads lead-id) err-not-found))
      (account (unwrap! (map-get? customer-accounts (get account-id lead)) err-not-found))
    )
    (asserts! (is-eq tx-sender (get organization account)) err-unauthorized)
    (asserts! (not (get converted lead)) err-already-exists)
    (map-set sales-leads lead-id (merge lead {
      converted: true,
      conversion-value: conversion-value,
      status: "converted"
    }))
    (ok true)
  )
)

(define-public (renew-subscription (account-id uint) (duration-blocks uint))
  (let
    (
      (account (unwrap! (map-get? customer-accounts account-id) err-not-found))
      (total-cost (* (get monthly-fee account) (/ duration-blocks u4320)))
    )
    (asserts! (is-eq tx-sender (get organization account)) err-unauthorized)
    (try! (stx-transfer? total-cost tx-sender (as-contract tx-sender)))
    (map-set customer-accounts account-id (merge account {
      subscription-end: (+ (get subscription-end account) duration-blocks),
      active: true
    }))
    (ok true)
  )
)

(define-read-only (get-account (account-id uint))
  (ok (map-get? customer-accounts account-id))
)

(define-read-only (get-lead (lead-id uint))
  (ok (map-get? sales-leads lead-id))
)

(define-read-only (get-org-accounts (org principal))
  (ok (map-get? org-accounts org))
)

(define-read-only (get-account-leads (account-id uint))
  (ok (map-get? account-leads account-id))
)

Functions (9)

FunctionAccessArgs
create-accountpublicsubscription-tier: (string-ascii 20
create-leadpublicaccount-id: uint, lead-data-hash: (buff 32
update-lead-statuspubliclead-id: uint, new-status: (string-ascii 20
convert-leadpubliclead-id: uint, conversion-value: uint
renew-subscriptionpublicaccount-id: uint, duration-blocks: uint
get-accountread-onlyaccount-id: uint
get-leadread-onlylead-id: uint
get-org-accountsread-onlyorg: principal
get-account-leadsread-onlyaccount-id: uint