Source Code

;; title: Healify
;; version:
;; summary:
;; description:



(define-trait healthcare-product-tracking-trait
  (
    (onboard-product (uint uint) (response bool uint))
    (modify-product-phase (uint uint) (response bool uint))
    (retrieve-product-timeline (uint) (response (list 10 {phase: uint, moment: uint}) uint))
    (attach-validation (uint uint principal) (response bool uint))
    (confirm-validation (uint uint) (response bool uint))
  )
)

;; traits
;;
;; Define product phase constants
(define-constant PHASE_PRODUCED u1)
(define-constant PHASE_EVALUATION u2)
(define-constant PHASE_ACTIVE u3)
(define-constant PHASE_SERVICED u4)

;; token definitions
;;
;; Define validation type constants
(define-constant VALIDATION_TYPE_HEALTH_ADMIN u1)
(define-constant VALIDATION_TYPE_EUROPEAN u2)
(define-constant VALIDATION_TYPE_QUALITY u3)
(define-constant VALIDATION_TYPE_SECURITY u4)

;; constants
;;
;; Error constants
(define-constant ERR_NO_PERMISSION (err u1))
(define-constant ERR_PRODUCT_NOT_FOUND (err u2))
(define-constant ERR_PHASE_UPDATE_FAILED (err u3))
(define-constant ERR_INVALID_PHASE (err u4))
(define-constant ERR_INVALID_VALIDATION (err u5))

(define-constant ERR_VALIDATION_ALREADY_EXISTS (err u6))

;; data vars
;;
;; Contract administrator
(define-data-var admin-address principal tx-sender)

;; data maps
;;
;; Current moment counter
(define-data-var moment-counter uint u0)

;; public functions
;;
;; Product tracking map
(define-map product-data 
  {product-id: uint} 
  {
    creator: principal,
    current-phase: uint,
    timeline: (list 10 {phase: uint, moment: uint})
  }
)

;; read only functions
;;
;; Validation tracking map
(define-map product-validations
  {product-id: uint, validation-type: uint}
  {
    validator: principal,
    moment: uint,
    active: bool
  }
)

;; private functions
;;
;; Approved oversight entities
(define-map oversight-entities
  {entity: principal, validation-type: uint}
  {authorized: bool}
)


;; ;; Only admin can perform certain actions
(define-read-only (is-admin (caller principal))
  (is-eq caller (var-get admin-address))
)


;; Get product timeline
(define-read-only (retrieve-product-timeline (product-id uint))
  (let 
    (
      (product (unwrap! (map-get? product-data {product-id: product-id}) ERR_PRODUCT_NOT_FOUND))
    )
    (ok (get timeline product))
  )
)

;; Get current product phase
(define-read-only (get-product-phase (product-id uint))
  (let 
    (
      (product (unwrap! (map-get? product-data {product-id: product-id}) ERR_PRODUCT_NOT_FOUND))
    )
    (ok (get current-phase product))
  )
)

;; Verify product validation
(define-read-only (confirm-validation (product-id uint) (validation-type uint))
  (let
    (
      (validation (unwrap! 
        (map-get? product-validations {product-id: product-id, validation-type: validation-type})
        ERR_INVALID_VALIDATION
      ))
    )
    (ok (get active validation))
  )
)

;; Get validation details
(define-read-only (get-validation-details (product-id uint) (validation-type uint))
  (ok (map-get? product-validations {product-id: product-id, validation-type: validation-type}))
)


;; Validate phase
(define-private (is-valid-phase (phase uint))
  (or 
    (is-eq phase PHASE_PRODUCED)
    (is-eq phase PHASE_EVALUATION)
    (is-eq phase PHASE_ACTIVE)
    (is-eq phase PHASE_SERVICED)
  )
)

;; Get current moment and increment counter
(define-private (get-current-moment)
  (begin
    (var-set moment-counter (+ (var-get moment-counter) u1))
    (var-get moment-counter)
  )
)

;; Validate validation type
(define-private (is-valid-validation-type (validation-type uint))
  (or
    (is-eq validation-type VALIDATION_TYPE_HEALTH_ADMIN)
    (is-eq validation-type VALIDATION_TYPE_EUROPEAN)
    (is-eq validation-type VALIDATION_TYPE_QUALITY)
    (is-eq validation-type VALIDATION_TYPE_SECURITY)
  )
)

;; Validate product ID
(define-private (is-valid-product-id (product-id uint))
  (and (> product-id u0) (<= product-id u1000000))
)

;; Validate entity principal
(define-private (is-valid-entity (entity principal))
  (and 
    (not (is-eq entity (var-get admin-address)))  ;; Entity can't be contract admin
    (not (is-eq entity tx-sender))                ;; Entity can't be the sender
    (not (is-eq entity 'SP000000000000000000002Q6VF78))  ;; Not zero address
  )
)


;; Check if sender is approved oversight entity
(define-private (is-oversight-entity (entity principal) (validation-type uint))
  (default-to 
    false
    (get authorized (map-get? oversight-entities {entity: entity, validation-type: validation-type}))
  )
)

;;;;;;;;; PUBLIC FUNCTION ;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;; Register a new product
(define-public (onboard-product (product-id uint) (initial-phase uint))
  (begin
    (asserts! (is-valid-product-id product-id) ERR_PRODUCT_NOT_FOUND)
    (asserts! (is-valid-phase initial-phase) ERR_INVALID_PHASE)
    (asserts! (or (is-admin tx-sender) (is-eq initial-phase PHASE_PRODUCED)) ERR_NO_PERMISSION)

    (map-set product-data 
      {product-id: product-id}
      {
        creator: tx-sender,
        current-phase: initial-phase,
        timeline: (list {phase: initial-phase, moment: (get-current-moment)})
      }
    )
    (ok true)
  )
)

;; Update product phase
(define-public (modify-product-phase (product-id uint) (new-phase uint))
  (let 
    (
      (product (unwrap! (map-get? product-data {product-id: product-id}) ERR_PRODUCT_NOT_FOUND))
    )
    (asserts! (is-valid-product-id product-id) ERR_PRODUCT_NOT_FOUND)
    (asserts! (is-valid-phase new-phase) ERR_INVALID_PHASE)
    (asserts! 
      (or 
        (is-admin tx-sender)
        (is-eq (get creator product) tx-sender)
      ) 
      ERR_NO_PERMISSION
    )

    (map-set product-data 
      {product-id: product-id}
      (merge product 
        {
          current-phase: new-phase,
          timeline: (unwrap-panic 
            (as-max-len? 
              (append (get timeline product) {phase: new-phase, moment: (get-current-moment)}) 
              u10
            )
          )
        }
      )
    )
    (ok true)
  )
)


;; Add oversight entity with additional validation
(define-public (add-oversight-entity (entity principal) (validation-type uint))
  (begin
    (asserts! (is-admin tx-sender) ERR_NO_PERMISSION)
    (asserts! (is-valid-validation-type validation-type) ERR_INVALID_VALIDATION)
    (asserts! (is-valid-entity entity) ERR_NO_PERMISSION)

    ;; After validation, we can safely use the entity
    (map-set oversight-entities
      {entity: entity, validation-type: validation-type}
      {authorized: true}
    )
    (ok true)
  )
)

;; Add validation to product
(define-public (attach-validation (product-id uint) (validation-type uint))
  (begin
    (asserts! (is-valid-product-id product-id) ERR_PRODUCT_NOT_FOUND)
    (asserts! (is-valid-validation-type validation-type) ERR_INVALID_VALIDATION)
    (asserts! (is-oversight-entity tx-sender validation-type) ERR_NO_PERMISSION)

    (asserts! 
      (is-none 
        (map-get? product-validations {product-id: product-id, validation-type: validation-type})
      )
      ERR_VALIDATION_ALREADY_EXISTS
    )

    (let
      ((validated-product-id product-id)
       (validated-validation-type validation-type))
      (map-set product-validations
        {product-id: validated-product-id, validation-type: validated-validation-type}
        {
          validator: tx-sender,
          moment: (get-current-moment),
          active: true
        }
      )
      (ok true)
    )
  )
)

;; Revoke validation
(define-public (withdraw-validation (product-id uint) (validation-type uint))
  (begin
    (asserts! (is-valid-product-id product-id) ERR_PRODUCT_NOT_FOUND)
    (asserts! (is-valid-validation-type validation-type) ERR_INVALID_VALIDATION)

    (let
      (
        (validation (unwrap! 
          (map-get? product-validations {product-id: product-id, validation-type: validation-type})
          ERR_INVALID_VALIDATION
        ))
        (validated-product-id product-id)
        (validated-validation-type validation-type)
      )
      (asserts! 
        (or
          (is-admin tx-sender)
          (is-eq (get validator validation) tx-sender)
        )
        ERR_NO_PERMISSION
      )

      (map-set product-validations
        {product-id: validated-product-id, validation-type: validated-validation-type}
        (merge validation {active: false})
      )
      (ok true)
    )
  )
)

;;

Functions (16)

FunctionAccessArgs
is-adminread-onlycaller: principal
retrieve-product-timelineread-onlyproduct-id: uint
get-product-phaseread-onlyproduct-id: uint
confirm-validationread-onlyproduct-id: uint, validation-type: uint
get-validation-detailsread-onlyproduct-id: uint, validation-type: uint
is-valid-phaseprivatephase: uint
get-current-momentprivate
is-valid-validation-typeprivatevalidation-type: uint
is-valid-product-idprivateproduct-id: uint
is-valid-entityprivateentity: principal
is-oversight-entityprivateentity: principal, validation-type: uint
onboard-productpublicproduct-id: uint, initial-phase: uint
modify-product-phasepublicproduct-id: uint, new-phase: uint
add-oversight-entitypublicentity: principal, validation-type: uint
attach-validationpublicproduct-id: uint, validation-type: uint
withdraw-validationpublicproduct-id: uint, validation-type: uint