Catalyst / admin/Apex 14.8 GB / 57.8 GB 40.0 GB free
Help Sign in

admin / Apex

public

Bid Management and Orchestration Tool with AI Capability

Code Issues Pull requests Pipelines Packages Security Insights Wiki Settings
Apex / Synapse-Apexv2 / backend / app / core / seed.py 5913 B · main
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
from decimal import Decimal

from sqlalchemy import select
from sqlalchemy.orm import Session

from app.core.config import settings
from app.core.security import hash_password
from app.models import (
    ROLE_ADMIN,
    ComplianceFramework,
    EffortRule,
    LicenceCost,
    ResourceType,
    User,
    WorkflowTemplate,
)

FRAMEWORKS = [
    ("ISO 27001", "Information security management system controls (Annex A)."),
    ("ISO 9001", "Quality management system requirements."),
    ("Cyber Essentials Plus", "UK NCSC baseline technical controls, independently verified."),
    ("NIST CSF", "Identify, Protect, Detect, Respond, Recover functions."),
    ("SOC 2", "Trust Services Criteria: security, availability, confidentiality."),
    ("GDPR / DPA 2018", "UK data protection principles and obligations."),
]

RESOURCE_TYPES = [
    ("Service Desk Analyst", "Support", 28, 55, "L1/L2 support, ITIL"),
    ("Network Engineer", "Infrastructure", 45, 85, "Cisco, firewalls, LAN/WAN"),
    ("Security Analyst", "Security", 50, 95, "SIEM, incident response"),
    ("Service Delivery Manager", "Management", 55, 110, "ITIL, governance, SLA"),
    ("Cloud Engineer", "Cloud", 55, 100, "Azure, AWS, IaC"),
    ("Project Manager", "Management", 55, 105, "Prince2, transition"),
]

EFFORT_RULES = [
    ("Service desk per 100 workstations", "per_endpoint", "workstations", 100, "Service Desk Analyst", 32, 0),
    ("Security monitoring per 100 servers", "per_endpoint", "servers", 100, "Security Analyst", 20, 0),
    ("Network support per site", "per_site", "sites", 1, "Network Engineer", 8, 16),
    ("Service delivery management (fixed)", "fixed", None, 1, "Service Delivery Manager", 34, 0),
    ("Transition project management (fixed)", "fixed", None, 1, "Project Manager", 0, 160),
]

LICENCES = [
    ("Endpoint protection", "Vendor A", "per_endpoint", 4.5, "monthly"),
    ("SIEM ingestion", "Vendor B", "per_endpoint", 2.0, "monthly"),
    ("RMM agent", "Vendor C", "per_endpoint", 1.25, "monthly"),
]

DEFAULT_WORKFLOW = {
    "name": "Standard bid workflow",
    "is_default": True,
    "stages": [
        {"key": "draft", "label": "Draft", "roles": ["bid_manager"]},
        {"key": "planning", "label": "Planning", "roles": ["bid_manager"]},
        {"key": "in_progress", "label": "In progress", "roles": ["bid_manager", "contributor"]},
        {"key": "in_review", "label": "In review", "roles": ["approver"]},
        {"key": "approved", "label": "Approved", "roles": ["approver"]},
        {"key": "submitted", "label": "Submitted", "roles": ["bid_manager"]},
    ],
    "milestones": [
        {"name": "Kick-off", "offset_working_days_before_submission": 0, "from": "start"},
        {"name": "Requirement review complete", "offset_working_days_before_submission": 18},
        {"name": "First drafts complete", "offset_working_days_before_submission": 12},
        {"name": "Red-team / quality review", "offset_working_days_before_submission": 6},
        {"name": "Pricing complete", "offset_working_days_before_submission": 5},
        {"name": "Approval", "offset_working_days_before_submission": 3},
        {"name": "Submission", "offset_working_days_before_submission": 0},
    ],
}


def _first(db: Session, model):
    return db.execute(select(model).limit(1)).scalar_one_or_none()


def run_seed(db: Session) -> None:
    # Admin user
    admin = db.execute(
        select(User).where(User.email == settings.admin_email)
    ).scalar_one_or_none()
    if not admin:
        db.add(
            User(
                email=settings.admin_email,
                name="Administrator",
                password_hash=hash_password(settings.admin_initial_password),
                roles=[ROLE_ADMIN],
                is_active=True,
                must_change_password=True,
            )
        )

    if not _first(db, ComplianceFramework):
        for name, desc in FRAMEWORKS:
            db.add(ComplianceFramework(name=name, description=desc, controls=[], active=True))

    rt_map = {}
    if not _first(db, ResourceType):
        for name, fam, cost, sell, skills in RESOURCE_TYPES:
            rt = ResourceType(
                name=name,
                role_family=fam,
                skills=[s.strip() for s in skills.split(",")],
                hourly_cost_rate=Decimal(str(cost)),
                hourly_sell_rate=Decimal(str(sell)),
                daily_cost_rate=Decimal(str(cost * 8)),
                daily_sell_rate=Decimal(str(sell * 8)),
                currency=settings.default_currency,
            )
            db.add(rt)
            db.flush()
            rt_map[name] = rt.id
    else:
        for rt in db.execute(select(ResourceType)).scalars():
            rt_map[rt.name] = rt.id

    if not _first(db, EffortRule):
        for name, trig, etype, qty, rtname, rec, one in EFFORT_RULES:
            db.add(
                EffortRule(
                    name=name,
                    trigger=trig,
                    endpoint_type=etype,
                    per_qty=Decimal(str(qty)),
                    resource_type_id=rt_map.get(rtname),
                    hours_recurring=Decimal(str(rec)),
                    hours_oneoff=Decimal(str(one)),
                    active=True,
                )
            )

    if not _first(db, LicenceCost):
        for name, vendor, unit, cost, billing in LICENCES:
            db.add(
                LicenceCost(
                    name=name, vendor=vendor, unit=unit,
                    unit_cost=Decimal(str(cost)), billing=billing, active=True,
                )
            )

    if not _first(db, WorkflowTemplate):
        db.add(
            WorkflowTemplate(
                name=DEFAULT_WORKFLOW["name"],
                is_default=True,
                stages=DEFAULT_WORKFLOW["stages"],
                milestones=DEFAULT_WORKFLOW["milestones"],
            )
        )

    db.commit()