Fix 3 deliverable bugs: PDF env catalogue, business case, drawio diagram

- oci_pdf_gen.py: add_environment_catalogue now auto-detects new schema
  (name/sizing/cost_pct) vs legacy (environment/tier/databases/ocpus),
  same fix as oci_deck_gen.py. Also normalizes cost_notes string to list.
- business-case-spec.yaml: created PharmaCorp spec (was using MELI).
  Fixed schema: risks as {migration_risks, do_nothing_risks}, roadmap
  as {phases, total_duration}, recommendation as {summary, next_steps}.
- diagram-spec.yaml: rewrote to match generator format
  (tenancy.regions[].vcns[].subnets[].services[] with explicit IDs).
  Now generates 231 cells, 11 containers, 15 services, 10 connections.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
root
2026-04-13 00:21:26 -03:00
parent d2b153c5ce
commit b0fcf8d0f3
5 changed files with 190 additions and 21 deletions

View File

@@ -0,0 +1,151 @@
# OCI Deal Accelerator — Business Case
# Demo: PharmaCorp Mexico — ExaCS migration from on-prem Exadata X6
business_case:
customer_name: "PharmaCorp Mexico"
prepared_by: "Carlos Mendoza — Solutions Architect"
date: "2026-04-12"
executive_summary: >
PharmaCorp Mexico operates 3 mission-critical Oracle databases (EBS R12, SAP, DW)
on aging Exadata X6 hardware. The hardware refresh quote is $1.8M and locks the
company into 5 more years of on-prem operations with no DR capability. Migration
to OCI ExaCS X11M reduces annual infrastructure costs by 61% ($1.75M over 3 years),
adds cross-region DR (RPO<15min, RTO<1h), and resolves the pending SOX audit
finding on automated patching — all while eliminating data center costs.
drivers:
primary: "hardware_refresh_avoidance"
urgency: "HW refresh due in 6 months — must decide now or commit $1.8M"
cost_of_inaction:
financial: "$1.8M HW refresh + $300K/yr support + $80K/yr DC costs = $2.88M over 3yr"
risk: "No DR today — single site, single point of failure for EBS production"
compliance: "SOX audit finding: manual quarterly patching is non-compliant"
tco_comparison:
current_state:
description: "On-premises Exadata X6 with hardware refresh"
line_items:
- item: "Hardware Refresh (Exadata X8M)"
year_1: 1800000
year_2: 0
year_3: 0
notes: "One-time CapEx"
- item: "Annual Support & Maintenance"
year_1: 220000
year_2: 220000
year_3: 220000
- item: "Data Center (power, cooling, space)"
year_1: 80000
year_2: 80000
year_3: 80000
- item: "DBA Operations (patching)"
year_1: 60000
year_2: 60000
year_3: 60000
- item: "DR Infrastructure"
year_1: 0
year_2: 0
year_3: 0
notes: "No DR — risk accepted"
total_3yr: 2880000
proposed_oci:
description: "OCI ExaCS X11M with Data Guard DR"
line_items:
- item: "ExaCS X11M Queretaro (Prod, BYOL)"
year_1: 98400
year_2: 98400
year_3: 98400
notes: "$8,200/mo"
- item: "ExaCS X11M Sao Paulo (DR, BYOL)"
year_1: 98400
year_2: 98400
year_3: 98400
notes: "$8,200/mo — Data Guard standby"
- item: "FastConnect 10Gbps Dual"
year_1: 36720
year_2: 36720
year_3: 36720
notes: "$3,060/mo"
- item: "OCI Vault + Monitoring + Storage"
year_1: 30000
year_2: 30000
year_3: 30000
notes: "$2,500/mo"
- item: "Migration (one-time)"
year_1: 50000
year_2: 0
year_3: 0
notes: "ZDM + Data Guard setup + testing"
total_3yr: 1130400
savings_3yr: 1749600
savings_pct: 61
roi:
investment: 50000
annual_savings: 583200
payback_months: 1
three_year_roi: "3,400%"
value_drivers:
- driver: "Cost Avoidance"
impact: "$1.75M saved over 3 years vs HW refresh"
evidence: "BYOL pricing + elimination of DC costs + automated patching"
- driver: "Risk Reduction"
impact: "Cross-region DR where none exists today"
evidence: "RPO<15min, RTO<1h with Data Guard + FSDR"
- driver: "Compliance"
impact: "SOX audit finding resolved"
evidence: "ExaCS automated patching + OCI Audit + Vault for key management"
- driver: "Operational Agility"
impact: "DBA freed from patching + infrastructure management"
evidence: "Oracle-managed ExaCS infrastructure, automated backups"
risks:
migration_risks:
- risk: "EBS customizations require testing"
mitigation: "Pre-Prod testing in Phase 2 before cutover"
- risk: "FastConnect provisioning delay (partner-dependent)"
mitigation: "Start in week 1; IPSec VPN as interim backup"
- risk: "HW refresh deadline pressure (6 months)"
mitigation: "16-week migration plan fits within window"
do_nothing_risks:
- risk: "No DR — single site, single point of failure for EBS"
mitigation: "Cannot be mitigated without investment"
- risk: "SOX audit finding remains unresolved (manual patching)"
mitigation: "Remediation requires automated patching — on-prem can't deliver"
- risk: "$1.8M HW refresh locks in 5 more years of on-prem"
mitigation: "Sunk cost — no cloud migration ROI for 5+ years"
recommendation:
summary: >
Proceed with OCI ExaCS migration. 61% cost reduction over 3 years ($1.75M saved),
cross-region DR capability, and SOX compliance resolution. The alternative
(HW refresh) costs $1.75M more and leaves DR + compliance gaps unresolved.
next_steps:
- "Board approval with TCO presentation — May 2026"
- "Provision OCI tenancy + ExaCS in Queretaro — June 2026"
- "Start FastConnect provisioning with partner — June 2026"
- "EBS customization inventory and Pre-Prod testing — June 2026"
- "Production cutover — September 2026"
roadmap:
total_duration: "16 weeks (May — September 2026)"
phases:
- phase: "Board Approval"
timeline: "May 2026"
key_action: "Present TCO + risk analysis to board"
- phase: "Foundation (networking + ExaCS)"
timeline: "June 2026 (4 weeks)"
key_action: "Provision OCI tenancy, ExaCS, FastConnect"
- phase: "EBS Migration"
timeline: "July 2026 (6 weeks)"
key_action: "Migrate EBS R12 with ZDM, configure Data Guard"
- phase: "SAP + DW Migration"
timeline: "August 2026 (4 weeks)"
key_action: "Migrate remaining databases"
- phase: "Cutover + Decommission"
timeline: "September 2026 (2 weeks)"
key_action: "Production cutover, decommission Exadata X6"

View File

@@ -142,7 +142,7 @@ endobj
endobj endobj
19 0 obj 19 0 obj
<< <<
/Author (Carlos Mendoza) /CreationDate (D:20260412231513-03'00') /Creator (\(unspecified\)) /Keywords () /ModDate (D:20260412231513-03'00') /Producer (ReportLab PDF Library - \(opensource\)) /Author (Carlos Mendoza) /CreationDate (D:20260413001815-03'00') /Creator (\(unspecified\)) /Keywords () /ModDate (D:20260413001815-03'00') /Producer (ReportLab PDF Library - \(opensource\))
/Subject (OCI Architecture Proposal) /Title (PharmaCorp Mexico \204 Oracle Database Migration to OCI) /Trapped /False /Subject (OCI Architecture Proposal) /Title (PharmaCorp Mexico \204 Oracle Database Migration to OCI) /Trapped /False
>> >>
endobj endobj
@@ -181,10 +181,10 @@ Gau0D?!#c?&:N_CbgW/j?!L$g^Wu7?8q>@-7nU((+*^X&-#p2l<48Luq]/7J#`q"tlTI8H[URM:RCOPJ
endobj endobj
25 0 obj 25 0 obj
<< <<
/Filter [ /ASCII85Decode /FlateDecode ] /Length 2236 /Filter [ /ASCII85Decode /FlateDecode ] /Length 2349
>> >>
stream stream
Gau`U=``=W%"?O+^dC2I[Y[=KeDYgsS2Atqe"j7Xh9P)8O_I=f%Tc/`m]TuZP'k3VI"\gfRFX2CiqabtKIIK1U\b!5"umX=aa4AZ_-dD1>9!j>i-]M5lbN(=@WrYkbi92P&+tpuc,B^9a+FL7%\D]I%$'B6<<W8QR[pXlFY("6AoZR6*=`j_e8lY7O:ub!aN!KFX]<dXoq<34YO=mqMdDiHi)2am62Cci5@Et]Z(!sF*QrNecLoUr'Fn\PKHcjH@Wb5^-`B=dd#O%8pj/X8Z(/fR>;<,DdE@jp`&b><1ChX<r5pEBQJejLKMef1cTU'SA75V"0R)s#(BgTqi=bX9dOBte>dRDF6A;q)(/k&QmPC+6BK)Kp[un#&M.r.`c]a,<99U25#<bq?-lnXp61-PNDJ(G%K`d$i/HM(!F"p.PNM"@qMu:rrm^sheF*Iq\au]aZnVRhqUA4Kd*!GgLe^#M"hBK<ZnU(MBj8,p<TDD[g3.Loe`]F*!?;YV(keLi[Yb0VT0!Fo85;Dc)h=tuM_7U`=3mW"%jLb`h5q'(I>cI*nA1tB(#ksn2A\OHh6f.fK]WZY5J$ne=I>dL3pHtNAU'T6/)/l712;lmuE#k5C<oC8WY<BM1;7gDY7V*D!]=jW?V0!:i3=H!ea<@'<M'51h@5>tn?=[VDPZc0k$MGAOQg(o7b8[jG.lJjjg&Gk4?";kL]f'kUUGd,27ZF,C$i=&Md(DfRNZaZ%OeL_FUbT$02/2(qrqirh"k1":f'1J`Z>>_K'krdsArfo\9BY)bk0@YQU%'"[2)Nn2I%h`[jD$P`8o8=n_Wp6)MrAlpg8^LG/Y=I3oN&BlB/Saq<?efM,1#J57lOM9"WVfOFsts-qARF]RMTp#.De(BB3"q6'^F'$MDGUu:&%O_2.TnW/bM4c]7IU+ame^WA7^pV.'WWaL0MY[kQXKN+@2iE\0sd(`+&JA$o=;=/;i@L9ZE1OMb.\UGAM.phs3rW:U5'J-.Whk472_"lXbMJ8Qr&/*PZ@>o5ZYpK2=EHUGRU#R0:[;,(`/D"Y/B/1A-U;=?`5`:b'PsG"=e#;)uSH=0!:)H'-*%X/no,1f;7ro:^PF<L'eRTue>49FIb.o,M%jLpuBf\Snit@uP9V\hWL<e@SR`O7@LbD>-0GXZ(?GH^lZNhJV`[SL5XmkE`'%2'boM)G^bnMs\L\1/3Z'kVq9<??a.kgqHqKd;dLt]Muo8pT%(A12P]H<Fm6iT@78Kc/$*FUoqJeHV0i/bs7Qkrhf<#^0mrn0ULRNi29='NGaMY8t!dfA?#,[-IETY<3T9H7&0=1qF;#=S+&9\bWfPgZ>,oSaC88%Yi!SEA;2DO`_)\3l7tOLWM"$B2!l<)oF%nlM\N<_)(FpuDDi`cfmegj).D8CDa[Y#m%Wa62PWrhN4%1aGL'$Fqj9"o*3[*a`,?bB`&\L19:OqBqh\1LmK/kDVSn/Ffb**C@l(FS<Z%=r\8'-.c_u71LLYb76GF<c<+ps6<aC\#Es\oo%X\p=k<3/EH>/P`TKk:dmO$QhQO?1&<BqK8rQ7;JmRE^.939sg'I,XmGQNg)a!N1=.d\hUG"p&il@"2dQo-hq5=U=>g*0OCleH8DK0T7"a*1WHn6YZarl//KK&s(Vmc^)W86t'M:_DNe$g?uO6O'H]<%016e!L^V2Ir--rQA]]gAOK_\@LsTY)U`cS]We>QPT$/R?`3d^.318dd^FFl/)Mbbon:YG"o-oIPW#!B"p"F$Cce+Pl9mQI=Bn*7sP>.Lb7+<&EPSs+KF5f9Z-8$>p^7*>Re:1>E&D10ED?$NlYfhN/1s:2Po2^.+OqU/fnO5gjf9s=f<5se:U?XDOcI,Ss^[UcC\)6/#lcIWG$NN`RU2fZ\F@<.?u`;eZ,=GRb@*nH_h4k!7M#h]p`*>3)p!Qa/IO/[V+?r);3TaAoGYIQ-n-7/4O5]TWNYa`?S@k37Z?UC*':ak<(D-h9Y24[#M>hn*_]d/]cD)594u88]K,@:SF@B_Gqq7W#D_:?c_1'*25-KM&Q=UL;c<3C@7OWP=_4NP[:)eZ0&EqY*"o!%$[&M[3;=P"D*muM5=s@+uDSMdIOo@;TgBKe=)k'MZRfT;$=H@^X\[TksW++RekF,/D@6j8jDa4e*h@8=+fHcP)gfN23Q+5@F@ho%olmIP=\bUPY3MQe`;%/U@u=K^I$?DX+U7W-p_ErH]a<8HYRrb.,:g6Fdpts%fQWdQ&``~>endstream Gau0F=``=U&:XAWfS="WD%q^)n%QoPijKN@Nhn)iN*ftMZC18[GW9SjI<P^TU25[L*-=<"@$'%>p:sui!u$0Or'*jU:1j"`4Ti]4[K'nY2U"A#A9RV4aRFT+$9/mXZQ4cBoG`SOo-4b&O"tZjn/N6BE#`5f&ss^tjF![;(iD^bYUtV82Ae>^T'LoXPaLJsECU79"%a,iLJg+G\eddb:@hp$(XZ_4k!-]K/'NGhEr@f<0g)phmPN6*nN=so=<tR)7UQG7M$O0H"YNF-b6:II33>.U&Q/,?jc9be"3[pY%GWmi-'Yot^tBn<B1ChR?61bX3!!o;[s-aD)Q#[VRc'Te.87ig9L1?DOR8`p$pRG[#p^1[Rbk`eO>=qrV+AXjlle"P/4IOoWMi4Jhpp*mh^=rMT]8`6^u4qfLWSVf'YV`-:K$L>4k.1*=Y!'+maqOieIG7uB.H"k#gm))"U?XT(@`1Q/:L(C\u+YSD&q5P/c:jrReL)l]l*B&F`_g);/.7;"OcmekP(O/^e@ZMl5s/CdV:YmUX3*'<qQX!iUI^]T>poNg"f]G4RgbW?:=Uu1/C:QkLinq[RJU&-+$J>Z@^\(#b1BYCBc\)#1l)`_jR8bXO0/E.e7j*p*Di83W;uJ79#*f^\MT![If!:4GqT:r5mRpI&]V470QqSn8GhqgdBoBn`JYb1+IV^-R[@T9ZL3Z3;YI]Z8'$6QtOf/%Rh,W!<Ek4%SrTH$;jh-C9fJ##70EASp_FmCD.J*\>QLYG7NrSn@(jECRA-HS)=2I2oekE,o_fqFgBa^oRId#%R0(r:b)+L*CQ+*oJhZO2)pCNkTA$u^uDAMhEHuB>N<:!Nb9a'$D/u9m>D61UTR6-rF(g):dns'7j^4b!cBpi'MC1A^2DU9PgNACkQ@C?_`Yo/C,#=g8OQ'VE&QDJGPq2XO)e#2&uhrABLP?]>Gfc=\[H#AhGI(@T+"nD_.jL=&%.1NFq;ilp2H`!!gEP:BWBU?.M"M,OWHC'eMA-p7>4.3g*`Ma(Mf&sW8d+,^?+]6]%/E@\+uTJdM2[1_-\gq30!qY/g?*#Et56RObqmT!&IWI,2(g,cN=U3:%3e0c:SW_<lM8m`>R]aI>Hei!u.888=ed@qGtX*<'i(7n=FMrGqYJ9Q*-*J8L%Q!,tj1C:h(o/k+7naaRT[;#*@3THEi:DR-J\&mu'5jYt$'$Y<G8GR8t%m&+=,O'r#$$&3Yb>4ib&TiJ)JXjXFdm.92t5Lf#Xac_H7]W33b[2/UY3F>hQ+-`F>X(TTG<@9dS<_gH[CNeSY.dBI78c&VP'A3[#&3p_"gm.Fe$T>&$h5K7'[H_ehI)bN]c=pBHgm>F*-mLq&fYJu'_&(P!pB*:HAj5dDe%g+pF$cA5-+s%itC/n7Tgn(eN^GY:KN36M4SRW3Od"aA,e'`l]@fFG'c!C%n`69=n!FCbVp$gt.J?Y+c*hi^7OG0)Z05*i*D3<9V<S.8#kL8**gG4lX(u"uUHFN"D1`-$m?4XC@/?acZq!>YqRs&#heC$jGcVE=l0jMNTo]crBiYN.4g,]mHV6.=4W[AQ>2&X#cXJM,*`CKVC2V,d(m:Bcj)Q/a'er3M)Bm`GL)PGrf*0`>?eMQXX?Bc&k!C-'rKUheh6_<FC(53K\H%*BD,.LsKeSd4M(=o[jOm2;@F'q0`7iS4:_8,"Acj(Q6I$[`G+&KGIKAYeTDt"X>k-"PN$aWo]KM$0PHF4mjFaETO(/kJ3-%AGb@$d3g3ZFS[\6s+"oBfWMk\65GDiPiZFohfC?LA53=qL%V/<0LsD<f`)iVI$]Yn=R#2\]uU0*Bqk3r".A^INGho"-tul/)JAbqWC2W(h0PIQ\G#DS99/oWCo;C:5K;;tqEi65<u:o`dfIO"3bc>+Qkl^[9GME-=5\D_Ei6>G/kJ[PK[_>=/cKDXEY1Fg.V:$qg%$Q!jJR2YH.ee<B>Up#I'iT)FkS)gemIglll5:Y)"_Z>T<V]%Nu":Gf]GMSJ%dqPucgh/cYEG.VCjp36hLh.$pNe/22f<YBA@O[I1rX'2Zt=V`@md^*Q-\'J1(Xr@UKb[$3ZpA1fj`34R(;1E^Ro/NbAbHalS4]hV<1r`u7Ij%%j`_TA/UuMd@N33s[`cCVUQ\>\Y2--P,UgPs/,S$T.7Xs=Ul5kVI]9`,1R25t)QX%DZLK:gFb9@E&,se"fSj?Hp"\gPI'M;1)q8Tala#Ybhl\!`W:l>ZBRj8#;LYp0"XIDa>8u$<%l>!9j+ahM`L[S`5XhfCV7,LEF23oKk``YC^V=,9f/=.iiO@g6YRTp@*%:8>t)fYL4#Pt/D6S.30..0oW1d,dI%cQs&p6*;?Ii9b0>l~>endstream
endobj endobj
26 0 obj 26 0 obj
<< <<
@@ -249,15 +249,15 @@ xref
0000005993 00000 n 0000005993 00000 n
0000008355 00000 n 0000008355 00000 n
0000010383 00000 n 0000010383 00000 n
0000012711 00000 n 0000012824 00000 n
0000014950 00000 n 0000015063 00000 n
0000017314 00000 n 0000017427 00000 n
0000018630 00000 n 0000018743 00000 n
0000019167 00000 n 0000019280 00000 n
trailer trailer
<< <<
/ID /ID
[<058687b5e54d5950ae70b0c7d0f56515><058687b5e54d5950ae70b0c7d0f56515>] [<8c841a256005e9c14418567efe6f7d83><8c841a256005e9c14418567efe6f7d83>]
% ReportLab generated PDF document -- digest (opensource) % ReportLab generated PDF document -- digest (opensource)
/Info 19 0 R /Info 19 0 R
@@ -265,5 +265,5 @@ trailer
/Size 31 /Size 31
>> >>
startxref startxref
20023 20136
%%EOF %%EOF

View File

@@ -619,10 +619,28 @@ class OCIPDFGenerator:
self._add_bullet_list(items) self._add_bullet_list(items)
def add_environment_catalogue(self, environments: list, def add_environment_catalogue(self, environments: list,
cost_notes: list = None): cost_notes=None):
"""Environment Catalogue section.""" """Environment Catalogue section."""
self._add_section_title("Environment Catalogue") self._add_section_title("Environment Catalogue")
# Normalize cost_notes to list
if isinstance(cost_notes, str):
cost_notes = [s.strip() for s in cost_notes.split(".") if s.strip()]
# Detect schema: new (name/sizing/cost_pct) vs legacy (environment/tier/databases/ocpus)
sample = environments[0] if environments else {}
if "sizing" in sample or "cost_pct" in sample:
headers = ["Environment", "Sizing", "Isolation", "Cost %"]
rows = [
[e.get("name", e.get("environment", "")),
e.get("sizing", ""),
e.get("isolation", ""),
f"{e.get('cost_pct', '')}%" if e.get("cost_pct", "") != "" else ""]
for e in environments
]
avail = self.PAGE_WIDTH - 2 * self.MARGIN
widths = [avail * 0.18, avail * 0.40, avail * 0.27, avail * 0.15]
else:
headers = ["Environment", "Tier", "Databases", "OCPUs", "Isolation"] headers = ["Environment", "Tier", "Databases", "OCPUs", "Isolation"]
rows = [ rows = [
[e.get("environment", ""), e.get("tier", ""), [e.get("environment", ""), e.get("tier", ""),