731 lines
32 KiB
C#
731 lines
32 KiB
C#
using System;
|
||
using System.Collections.Generic;
|
||
using System.Globalization;
|
||
using System.Linq;
|
||
using QuestPDF.Drawing;
|
||
using QuestPDF.Fluent;
|
||
using QuestPDF.Helpers;
|
||
using QuestPDF.Infrastructure;
|
||
|
||
namespace PSTW_CentralSystem.Areas.IT.Printing
|
||
{
|
||
public class ItRequestPdfService
|
||
{
|
||
public byte[] Generate(ItRequestReportModel m)
|
||
{
|
||
QuestPDF.Settings.License = LicenseType.Community;
|
||
|
||
return Document.Create(container =>
|
||
{
|
||
container.Page(page =>
|
||
{
|
||
page.Size(PageSizes.A4);
|
||
page.Margin(14);
|
||
page.DefaultTextStyle(x => x.FontSize(7));
|
||
|
||
page.Content().Column(col =>
|
||
{
|
||
col.Item().Element(e => HeaderStrip(e, m));
|
||
|
||
|
||
col.Item().PaddingTop(4).Text(
|
||
"This form is digitally generated. Submit to http://support.transwater.com.my");
|
||
|
||
// ===== SECTION A =====
|
||
|
||
col.Item().PaddingTop(4).Text("Section A").Bold().FontSize(7);
|
||
col.Item().Element(e => SectionA_IdentityEmployment(e, m));
|
||
|
||
|
||
|
||
// two-column layout (left = Hardware+OS+Software, right = Email+Internet+Shared+Copier)
|
||
col.Item().Table(t =>
|
||
{
|
||
t.ColumnsDefinition(cols =>
|
||
{
|
||
cols.RelativeColumn(1); // LEFT
|
||
cols.ConstantColumn(8); // gutter
|
||
cols.RelativeColumn(1); // RIGHT
|
||
});
|
||
|
||
// left cell (entire left stack)
|
||
t.Cell()
|
||
.Element(x => x.MinHeight(380)) // optional: set a floor so both look balanced
|
||
.Element(e => SectionA_HardwareOsSoftware(e, m));
|
||
|
||
// gutter cell
|
||
t.Cell().Text("");
|
||
|
||
// right cell (entire right stack)
|
||
t.Cell()
|
||
.Element(x => x.MinHeight(380)) // same floor as left
|
||
.Element(e => SectionA_RightPane_EmailInternetShared(e, m));
|
||
});
|
||
col.Item().Element(e => FormArrangementBlock(e, m));
|
||
col.Item().Element(e => SectionB_TwoBlocks(e, m));
|
||
});
|
||
});
|
||
}).GeneratePdf();
|
||
}
|
||
|
||
// ---------------- helpers & styles ----------------
|
||
#region HELPERS
|
||
static string Box(bool on) => on ? "☒" : "☐";
|
||
static string F(DateTime? dt) => dt.HasValue ? dt.Value.ToString("dd/MM/yyyy", CultureInfo.InvariantCulture) : "";
|
||
static IContainer Cell(IContainer x) => x.Border(1).BorderColor(Colors.Grey.Lighten2).Padding(4);
|
||
static IContainer CellHead(IContainer x) => x.Background(Colors.Grey.Lighten4).Border(1).BorderColor(Colors.Grey.Lighten2).Padding(4);
|
||
static IContainer CellMandatory(IContainer x) => x.Background(Colors.Grey.Lighten2).Border(1).BorderColor(Colors.Grey.Lighten2).Padding(4);
|
||
#endregion
|
||
|
||
// ================= HEADER (boxed like your screenshot) =================
|
||
void HeaderStrip(IContainer c, ItRequestReportModel m)
|
||
{
|
||
c.Border(1).Padding(0).Table(t =>
|
||
{
|
||
t.ColumnsDefinition(cols =>
|
||
{
|
||
cols.RelativeColumn(2); // LEFT: big title
|
||
cols.RelativeColumn(1); // RIGHT: meta table
|
||
});
|
||
|
||
// LEFT pane: centered title
|
||
t.Cell().BorderRight(1).Padding(8).MinHeight(10).AlignCenter().AlignMiddle().Column(left =>
|
||
{
|
||
left.Item().Text("I.T. REQUEST FORM").SemiBold().FontSize(14).AlignCenter();
|
||
left.Item().Text("(Group IT)").SemiBold().FontSize(14).AlignCenter();
|
||
});
|
||
|
||
// RIGHT pane: 2-column grid with borders
|
||
t.Cell().Padding(0).Element(x => RightMetaBox(x, m));
|
||
});
|
||
}
|
||
|
||
// draws the right-side 2-column table with boxed rows
|
||
void RightMetaBox(IContainer c, ItRequestReportModel m)
|
||
{
|
||
c.Table(t =>
|
||
{
|
||
t.ColumnsDefinition(cols =>
|
||
{
|
||
cols.RelativeColumn(1); // label
|
||
cols.RelativeColumn(1); // value
|
||
});
|
||
|
||
void Row(string label, string value, bool isLast = false)
|
||
{
|
||
// label cell (left)
|
||
t.Cell().BorderBottom(1).Padding(2).Text(label);
|
||
// value cell (right) — add vertical divider between label/value
|
||
t.Cell().BorderLeft(1).BorderBottom(1).Padding(0).AlignMiddle().Text(value ?? "");
|
||
}
|
||
|
||
Row("Document No.", m.DocumentNo);
|
||
Row("Effective Date", (m.EffectiveDate == default) ? "" : m.EffectiveDate.ToString("dd/MM/yyyy"));
|
||
Row("Rev. No", m.RevNo); // <- shows dynamic StatusId value
|
||
Row("Doc. Page No", m.DocPageNo); // last row still gets bottom border for boxed look
|
||
});
|
||
}
|
||
|
||
|
||
// ================= SECTION A =================
|
||
#region SECTION A • Identity & Employment
|
||
// ================= SECTION A – Identity & Employment (refined layout) =================
|
||
// SECTION A — Identity + Employment as ONE BLOCK (matches screenshot)
|
||
// ================= SECTION A – Compact Unified Block (new refined layout) =================
|
||
void SectionA_IdentityEmployment(IContainer c, ItRequestReportModel m)
|
||
{
|
||
// helpers
|
||
var emp = (m.EmploymentStatus ?? "").Trim().ToLowerInvariant();
|
||
bool isPerm = emp == "permanent";
|
||
bool isContract = emp == "contract";
|
||
bool isTemp = emp == "temp" || emp == "temporary";
|
||
bool isNew = emp == "new staff" || emp == "new";
|
||
|
||
IContainer L(IContainer x) => x.Border(1).BorderColor(Colors.Grey.Lighten2).Padding(4);
|
||
IContainer V(IContainer x) => x.Border(1).BorderColor(Colors.Grey.Lighten2).Padding(4);
|
||
|
||
c.Table(t =>
|
||
{
|
||
// 6-column consistent grid
|
||
t.ColumnsDefinition(cols =>
|
||
{
|
||
cols.RelativeColumn(1); // L1
|
||
cols.RelativeColumn(2); // V1
|
||
cols.RelativeColumn(1); // L2
|
||
cols.RelativeColumn(2); // V2
|
||
cols.RelativeColumn(1); // L3
|
||
cols.RelativeColumn(2); // V3
|
||
});
|
||
|
||
// === Row 1: Staff Name / Company / Div ===
|
||
t.Cell().Element(L).Text("Staff Name:");
|
||
t.Cell().Element(V).Text(m.StaffName ?? "");
|
||
t.Cell().Element(L).Text("Company:");
|
||
t.Cell().Element(V).Text(m.CompanyName ?? "");
|
||
t.Cell().Element(L).Text("Div/Dept:");
|
||
t.Cell().Element(V).Text(m.DepartmentName ?? "");
|
||
|
||
// === Row 2: Designation / Location ===
|
||
t.Cell().Element(L).Text("Designation:");
|
||
t.Cell().Element(V).Text(m.Designation ?? "");
|
||
t.Cell().Element(L).Text("Location:");
|
||
t.Cell().Element(V).Text(m.Location ?? "");
|
||
// fill the last two cells to maintain full-width grid
|
||
t.Cell().Element(L).Text("");
|
||
t.Cell().Element(V).Text("");
|
||
|
||
// === Row 3: Employment Status + Contract End Date beside it ===
|
||
t.Cell().Element(L).Text("Employment Status:");
|
||
t.Cell().ColumnSpan(3).Element(V).Row(r =>
|
||
{
|
||
r.Spacing(12);
|
||
r.ConstantItem(50).Text($"{Box(isPerm)} Permanent");
|
||
r.ConstantItem(50).Text($"{Box(isContract)} Contract");
|
||
r.ConstantItem(50).Text($"{Box(isTemp)} Temp");
|
||
r.ConstantItem(50).Text($"{Box(isNew)} New Staff");
|
||
});
|
||
|
||
t.Cell().Element(L).Text("If Temp / Contract End Date:");
|
||
t.Cell().Element(V).Text(F(m.ContractEndDate));
|
||
|
||
// === Row 4: Phone Ext + Required Date beside it ===
|
||
t.Cell().Element(L).Text("Phone Ext:");
|
||
t.Cell().Element(V).Text(m.PhoneExt ?? "");
|
||
t.Cell().Element(L).Text("Required Date:");
|
||
t.Cell().Element(V).Text(F(m.RequiredDate));
|
||
// keep remaining two cells empty to close grid
|
||
t.Cell().Element(L).Text("");
|
||
t.Cell().Element(V).Text("");
|
||
});
|
||
}
|
||
|
||
|
||
|
||
|
||
#endregion
|
||
|
||
#region SECTION A • HardwareOsSoftware
|
||
|
||
// ===================== SECTION A – HARDWARE + OS + SOFTWARE =====================
|
||
void SectionA_HardwareOsSoftware(IContainer c, ItRequestReportModel m)
|
||
{
|
||
bool HasSoft(string name) =>
|
||
m.Software.Any(s => (s.Name ?? "").Equals(name, StringComparison.InvariantCultureIgnoreCase));
|
||
|
||
var general = new[] { "MS Word", "MS Excel", "MS Outlook", "MS PowerPoint", "MS Access", "MS Project", "Acrobat Standard", "AutoCAD", "Worktop/ERP Login" };
|
||
var utility = new[] { "PDF Viewer", "7Zip", "AutoCAD Viewer", "Smart Draw" };
|
||
|
||
c.Table(t =>
|
||
{
|
||
t.ColumnsDefinition(cols =>
|
||
{
|
||
cols.RelativeColumn(1);
|
||
});
|
||
|
||
// --- HEADER: Hardware Requirements ---
|
||
t.Cell().Element(x => x.Background(Colors.Black).Padding(3))
|
||
.Text("Hardware Requirements").FontColor(Colors.White).Bold();
|
||
|
||
// --- Hardware Body ---
|
||
t.Cell().Border(1).Padding(1).Column(col =>
|
||
{
|
||
col.Spacing(5);
|
||
col.Item().Row(r =>
|
||
{
|
||
// Left column: Purpose + Justification
|
||
r.RelativeItem().Column(left =>
|
||
{
|
||
left.Item().Text($"{Box(m.HwPurposeNewRecruitment)} New Staff Recruitment");
|
||
left.Item().Text($"{Box(m.HwPurposeReplacement)} Replacement");
|
||
left.Item().Text($"{Box(m.HwPurposeAdditional)} Additional");
|
||
left.Item().PaddingTop(5).Text("Justification (for hardware change) :");
|
||
left.Item().Border(1).Height(40).Padding(4)
|
||
.Text(string.IsNullOrWhiteSpace(m.Justification) ? "" : m.Justification);
|
||
});
|
||
|
||
// Right column: Category selection
|
||
r.RelativeItem().Column(right =>
|
||
{
|
||
right.Item().Text("Select below:");
|
||
right.Item().Text($"{Box(m.HwDesktopAllIn)} Desktop (all inclusive)");
|
||
right.Item().Text($"{Box(m.HwNotebookAllIn)} Notebook (all inclusive)");
|
||
right.Item().Text($"{Box(m.HwDesktopOnly)} Desktop only");
|
||
right.Item().Text($"{Box(m.HwNotebookOnly)} Notebook only");
|
||
right.Item().Text($"{Box(m.HwNotebookBattery)} Notebook battery");
|
||
right.Item().Text($"{Box(m.HwPowerAdapter)} Power Adapter");
|
||
right.Item().Text($"{Box(m.HwMouse)} Computer Mouse");
|
||
right.Item().Text($"{Box(m.HwExternalHdd)} External Hard Drive");
|
||
right.Item().Text("Other (Specify):");
|
||
right.Item().Border(1).Height(18).Padding(3)
|
||
.Text(string.IsNullOrWhiteSpace(m.HwOtherText) ? "-" : m.HwOtherText);
|
||
});
|
||
});
|
||
});
|
||
|
||
// --- HEADER: OS Requirements ---
|
||
t.Cell().Element(x => x.Background(Colors.Black).Padding(3))
|
||
.Text("OS Requirements (Leave blank if no specific requirement)")
|
||
.FontColor(Colors.White).Bold();
|
||
|
||
// --- OS Body ---
|
||
t.Cell().Border(1).Padding(5).Column(col =>
|
||
{
|
||
col.Item().Text("Requirements:");
|
||
col.Item().Border(1).Height(30).Padding(4)
|
||
.Text(m.OsRequirements.Any() ? string.Join(Environment.NewLine, m.OsRequirements) : "-");
|
||
});
|
||
|
||
// --- HEADER: Software Requirements ---
|
||
t.Cell().Element(x => x.Background(Colors.Black).Padding(3))
|
||
.Text("Software Requirements").FontColor(Colors.White).Bold();
|
||
|
||
// --- Software Body (3 columns) ---
|
||
t.Cell().Border(1).Padding(5).Table(st =>
|
||
{
|
||
st.ColumnsDefinition(cols =>
|
||
{
|
||
cols.RelativeColumn(1); // General
|
||
cols.RelativeColumn(1); // Utility
|
||
cols.RelativeColumn(1); // Custom
|
||
});
|
||
|
||
// Headings
|
||
st.Header(h =>
|
||
{
|
||
h.Cell().Element(CellHead).Text("General Software");
|
||
h.Cell().Element(CellHead).Text("Utility Software");
|
||
h.Cell().Element(CellHead).Text("Custom Software");
|
||
});
|
||
|
||
int maxRows = Math.Max(general.Length, utility.Length);
|
||
for (int i = 0; i < maxRows; i++)
|
||
{
|
||
st.Cell().Element(Cell)
|
||
.Text(i < general.Length ? $"{Box(HasSoft(general[i]))} {general[i]}" : "");
|
||
st.Cell().Element(Cell)
|
||
.Text(i < utility.Length ? $"{Box(HasSoft(utility[i]))} {utility[i]}" : "");
|
||
|
||
if (i == 0)
|
||
{
|
||
st.Cell().Element(Cell).Text("Others (Specify) :");
|
||
}
|
||
else if (i == 1)
|
||
{
|
||
st.Cell().Element(Cell).Border(1).Height(15).Padding(3).Text("-");
|
||
}
|
||
else st.Cell().Element(Cell).Text("");
|
||
}
|
||
});
|
||
});
|
||
}
|
||
|
||
|
||
|
||
#endregion
|
||
|
||
#region SECTION A • EmailInternetSharedperm
|
||
// ===================== SECTION A – RIGHT PANE =====================
|
||
void SectionA_RightPane_EmailInternetShared(IContainer c, ItRequestReportModel m)
|
||
{
|
||
c.Column(col =>
|
||
{
|
||
// ===== Email =====
|
||
col.Item().Element(x => x.Background(Colors.Black).Padding(3))
|
||
.Text("Email").FontColor(Colors.White).Bold();
|
||
|
||
col.Item().Border(1).Padding(6).Column(cc =>
|
||
{
|
||
// single-line "Email Address:" with inline box
|
||
cc.Item().Row(r =>
|
||
{
|
||
r.ConstantItem(100).Text("Email Address:"); // label column width
|
||
r.RelativeItem().Border(1).Height(16).PaddingHorizontal(4).AlignMiddle()
|
||
.Text(m.Emails.Any() ? string.Join("; ", m.Emails) : "");
|
||
});
|
||
|
||
cc.Item().PaddingTop(4).Text("Arrangement Guide: FirstName&LastName or Name&Surname or Surname&Name.");
|
||
cc.Item().Text("Full name and short form/ initial is allowed to be used if the name is too long.");
|
||
cc.Item().Text("e.g. siti.nurhaliza, jackie.chan, ks.chan");
|
||
});
|
||
|
||
// ===== Internet Permissions =====
|
||
col.Item().Element(x => x.Background(Colors.Black).Padding(3))
|
||
.Text("Internet Permissions").FontColor(Colors.White).Bold();
|
||
|
||
col.Item().Border(1).Padding(0).Column(cc =>
|
||
{
|
||
cc.Item().BorderBottom(1).Padding(6).Text($"{Box(false)} Unlimited Internet Access");
|
||
cc.Item().BorderBottom(1).Padding(6).Text($"{Box(false)} Limited Internet Access");
|
||
cc.Item().BorderBottom(1).Padding(6).Text($"{Box(false)} PSI Instant Messenger");
|
||
cc.Item().BorderBottom(1).Padding(6).Text($"{Box(false)} VPN");
|
||
|
||
cc.Item().PaddingLeft(14).PaddingTop(4).Text("Justification for the Internet Permissions:");
|
||
cc.Item().Padding(6).Border(1).Height(20).Padding(4).Text("-");
|
||
});
|
||
|
||
// ===== Shared Permissions =====
|
||
col.Item().PaddingTop(0).Element(x => x.Background(Colors.Black).Padding(3))
|
||
.Text("Shared Permissions").FontColor(Colors.White).Bold();
|
||
|
||
col.Item().Border(1).Padding(0).Element(x => SharedPermissionsTable(x, m));
|
||
|
||
// ===== Copier =====
|
||
col.Item().PaddingTop(0).Element(x => x.Border(1).Padding(8)).Column(cc =>
|
||
{
|
||
cc.Item().Row(rr =>
|
||
{
|
||
rr.RelativeItem().Row(r1 =>
|
||
{
|
||
r1.RelativeItem().Text("Copier Scanner");
|
||
r1.RelativeItem().Text($"{Box(true)} Black");
|
||
r1.RelativeItem().Text($"{Box(false)} Color");
|
||
});
|
||
|
||
rr.RelativeItem().Row(r2 =>
|
||
{
|
||
r2.RelativeItem().Text("Copier Printing");
|
||
r2.RelativeItem().Text($"{Box(true)} Black");
|
||
r2.RelativeItem().Text($"{Box(false)} Color");
|
||
});
|
||
});
|
||
});
|
||
});
|
||
}
|
||
void SharedPermissionsTable(IContainer c, ItRequestReportModel m)
|
||
{
|
||
c.Table(t =>
|
||
{
|
||
t.ColumnsDefinition(cols =>
|
||
{
|
||
cols.ConstantColumn(18); // #
|
||
cols.RelativeColumn(6); // Share
|
||
cols.RelativeColumn(1); // Read
|
||
cols.RelativeColumn(1); // Write
|
||
cols.RelativeColumn(1); // Delete
|
||
cols.RelativeColumn(1); // Remove
|
||
});
|
||
|
||
// header band
|
||
t.Header(h =>
|
||
{
|
||
h.Cell().Element(CellHead).Text("");
|
||
h.Cell().Element(CellHead).Text("Shared Permissions");
|
||
h.Cell().Element(CellHead).Text("Read");
|
||
h.Cell().Element(CellHead).Text("Write");
|
||
h.Cell().Element(CellHead).Text("Delete");
|
||
h.Cell().Element(CellHead).Text("Remove");
|
||
});
|
||
|
||
var rows = m.SharedPerms.Select((sp, i) => new
|
||
{
|
||
Index = i + 1,
|
||
sp.Share,
|
||
sp.R,
|
||
sp.W,
|
||
sp.D,
|
||
sp.Remove
|
||
}).ToList();
|
||
|
||
foreach (var r in rows)
|
||
{
|
||
t.Cell().Element(Cell).Text(r.Index.ToString());
|
||
t.Cell().Element(Cell).Text(r.Share ?? "");
|
||
t.Cell().Element(Cell).Text(Box(r.R));
|
||
t.Cell().Element(Cell).Text(Box(r.W));
|
||
t.Cell().Element(Cell).Text(Box(r.D));
|
||
t.Cell().Element(Cell).Text(Box(r.Remove));
|
||
}
|
||
|
||
int start = rows.Count + 1; // no hardcoded row; if no data, start at 1
|
||
|
||
for (int i = start; i <= 6; i++)
|
||
{
|
||
t.Cell().Element(Cell).Text(i.ToString());
|
||
t.Cell().Element(Cell).Text("");
|
||
t.Cell().Element(Cell).Text("");
|
||
t.Cell().Element(Cell).Text("");
|
||
t.Cell().Element(Cell).Text("");
|
||
t.Cell().Element(Cell).Text("");
|
||
}
|
||
});
|
||
}
|
||
|
||
|
||
#endregion
|
||
|
||
#region SECTION A • OS Requirements
|
||
// ===================== SECTION A – Form Arrangement =====================
|
||
|
||
void FormArrangementBlock(IContainer c, ItRequestReportModel m)
|
||
{
|
||
// tiny helper: draws the vertical borders for each cell so it looks like 5 boxed panels
|
||
IContainer BoxCell(IContainer x, bool isLast) =>
|
||
x.BorderLeft(1)
|
||
.BorderRight(isLast ? 1 : 0) // last cell closes the right border
|
||
.Padding(6)
|
||
.MinHeight(45); // keep all equal; adjust to taste
|
||
|
||
c.Column(col =>
|
||
{
|
||
// italic guide line
|
||
col.Item()
|
||
.PaddingBottom(4)
|
||
.Text("Form Arrangement: User → HOD → IT HOD → FINANCE HOD → CEO/CFO/COO")
|
||
.Italic();
|
||
|
||
// OUTER frame
|
||
col.Item().Border(1).Element(frame =>
|
||
{
|
||
frame.Table(t =>
|
||
{
|
||
// 5 equal columns
|
||
t.ColumnsDefinition(cols =>
|
||
{
|
||
cols.RelativeColumn(1);
|
||
cols.RelativeColumn(1);
|
||
cols.RelativeColumn(1);
|
||
cols.RelativeColumn(1);
|
||
cols.RelativeColumn(1);
|
||
});
|
||
|
||
// local function to render a boxed panel
|
||
void Panel(int index0to4, string title, string name, string date)
|
||
{
|
||
bool last = index0to4 == 4;
|
||
t.Cell().Element(x => BoxCell(x, last)).Column(cc =>
|
||
{
|
||
cc.Item().Text(title);
|
||
|
||
// signature line
|
||
|
||
|
||
// Name / Date rows
|
||
cc.Item().PaddingTop(8).Row(r =>
|
||
{
|
||
r.ConstantItem(40).Text("Name :");
|
||
r.RelativeItem().Text(string.IsNullOrWhiteSpace(name) ? "" : name);
|
||
});
|
||
cc.Item().Row(r =>
|
||
{
|
||
r.ConstantItem(40).Text("Date :");
|
||
r.RelativeItem().Text(string.IsNullOrWhiteSpace(date) ? "" : date);
|
||
});
|
||
});
|
||
}
|
||
|
||
// build the 5 panels (plug in your resolved names/dates)
|
||
Panel(0, "Requested by:", m.RequestorName ?? "", F(m.SubmitDate) ?? "");
|
||
Panel(1, "Approved by HOD:", m.HodApprovedBy ?? "", F(m.HodSubmitDate) ?? "");
|
||
Panel(2, "Approved by Group IT HOD:", m.GitHodApprovedBy ?? "", F(m.GitHodSubmitDate) ?? "");
|
||
Panel(3, "Supported by Finance HOD:", m.FinHodApprovedBy ?? "", F(m.FinHodSubmitDate) ?? "");
|
||
Panel(4, "Reviewed & Approved by Management:", m.MgmtApprovedBy ?? "", F(m.MgmtSubmitDate) ?? "");
|
||
});
|
||
});
|
||
});
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region SECTION A • Approvals
|
||
void Approvals(IContainer c, ItRequestReportModel m)
|
||
{
|
||
c.Column(col =>
|
||
{
|
||
col.Item().Row(r =>
|
||
{
|
||
r.RelativeItem().Column(cc =>
|
||
{
|
||
cc.Item().Text("Requested by:");
|
||
cc.Item().PaddingTop(12).Text("Name : MANDATORY");
|
||
cc.Item().Row(rr =>
|
||
{
|
||
rr.ConstantItem(40).Text("Date :");
|
||
rr.RelativeItem().Border(1).Height(14).Text(F(m.SubmitDate));
|
||
});
|
||
});
|
||
|
||
r.RelativeItem().Column(cc =>
|
||
{
|
||
cc.Item().Text("Approved by HOD:");
|
||
cc.Item().PaddingTop(12).Text("Name :");
|
||
cc.Item().Row(rr =>
|
||
{
|
||
rr.ConstantItem(40).Text("Date :");
|
||
rr.RelativeItem().Border(1).Height(16).Text("");
|
||
});
|
||
});
|
||
});
|
||
|
||
col.Item().Row(r =>
|
||
{
|
||
r.RelativeItem().Column(cc =>
|
||
{
|
||
cc.Item().Text("Approved by Group IT HOD:");
|
||
cc.Item().PaddingTop(12).Text("Name :");
|
||
cc.Item().Row(rr =>
|
||
{
|
||
rr.ConstantItem(40).Text("Date :");
|
||
rr.RelativeItem().Border(1).Height(16).Text("");
|
||
});
|
||
});
|
||
|
||
r.RelativeItem().Column(cc =>
|
||
{
|
||
cc.Item().Text("Supported by Finance HOD:");
|
||
cc.Item().PaddingTop(12).Text("Name :");
|
||
cc.Item().Row(rr =>
|
||
{
|
||
rr.ConstantItem(40).Text("Date :");
|
||
rr.RelativeItem().Border(1).Height(16).Text("");
|
||
});
|
||
});
|
||
});
|
||
|
||
col.Item().Row(r =>
|
||
{
|
||
r.RelativeItem().Column(cc =>
|
||
{
|
||
cc.Item().Text("Reviewed & Approved by");
|
||
cc.Item().Text("Management:");
|
||
cc.Item().PaddingTop(12).Text("Name :");
|
||
cc.Item().Row(rr =>
|
||
{
|
||
rr.ConstantItem(40).Text("Date :");
|
||
rr.RelativeItem().Border(1).Height(16).Text("");
|
||
});
|
||
});
|
||
|
||
r.RelativeItem().Text("");
|
||
});
|
||
});
|
||
}
|
||
#endregion
|
||
|
||
// ================= SECTION B =================
|
||
#region SECTION B • Asset Information/ Acknowledgment
|
||
|
||
void SectionB_TwoBlocks(IContainer c, ItRequestReportModel m)
|
||
{
|
||
c.Column(col =>
|
||
{
|
||
// Title line exactly like screenshot (italic note on same line)
|
||
col.Item().Text(text =>
|
||
{
|
||
text.Span("Section B ").Bold();
|
||
text.Span("(To be completed by IT Staff only)").Italic();
|
||
});
|
||
|
||
// ===== Block 1: Asset Information (left) + Remarks (right) =====
|
||
col.Item().PaddingTop(4).Border(1).Element(block1 =>
|
||
{
|
||
block1.Table(t =>
|
||
{
|
||
t.ColumnsDefinition(cols =>
|
||
{
|
||
cols.RelativeColumn(1);
|
||
cols.ConstantColumn(1); // skinny divider (we'll draw borders on cells)
|
||
cols.RelativeColumn(1);
|
||
});
|
||
|
||
// Header row with black bands
|
||
// Left header
|
||
t.Cell().Element(x => x.Background(Colors.Black).Padding(3).BorderRight(1))
|
||
.Text("Asset Information").FontColor(Colors.White).Bold();
|
||
// divider (invisible content, keeps structure)
|
||
t.Cell().BorderLeft(0).BorderRight(0).Text("");
|
||
// Right header
|
||
t.Cell().Element(x => x.Background(Colors.Black).Padding(3))
|
||
.Text("Remarks:-").FontColor(Colors.White).Bold();
|
||
|
||
// Content row (equal height because same table row)
|
||
// Left: asset info table
|
||
t.Cell().Element(x => x.BorderTop(1).BorderRight(1).Padding(0))
|
||
.Element(x => SectionB_AssetInfoTable(x, m));
|
||
|
||
// divider
|
||
t.Cell().Border(0).Text("");
|
||
|
||
// Right: remarks box
|
||
t.Cell().Element(x => x.BorderTop(1).Padding(6).MinHeight(108))
|
||
.Text(string.IsNullOrWhiteSpace(m.Remarks) ? "" : m.Remarks);
|
||
});
|
||
});
|
||
|
||
// ===== Block 2: Requestor Acknowledgement (left) + Completed By (right) =====
|
||
// ===== Block 2: Requestor Acknowledgement (left) + Completed By (right) =====
|
||
col.Item().PaddingTop(6).Border(1).Element(block2 =>
|
||
{
|
||
block2.Table(t =>
|
||
{
|
||
t.ColumnsDefinition(cols =>
|
||
{
|
||
cols.RelativeColumn(1);
|
||
cols.ConstantColumn(1); // divider
|
||
cols.RelativeColumn(1);
|
||
});
|
||
|
||
// Left pane (no signature line, compact height)
|
||
t.Cell().Element(x => x.Padding(8).BorderRight(1)).Column(cc =>
|
||
{
|
||
cc.Item().Text("Requestor Acknowledgement:").Bold();
|
||
cc.Item().PaddingTop(4).Row(r =>
|
||
{
|
||
r.ConstantItem(44).Text("Name:");
|
||
r.RelativeItem().Text(m.RequestorName ?? "");
|
||
r.ConstantItem(44).Text("Date:");
|
||
r.RelativeItem().Text(F(m.RequestorAcceptedAt));
|
||
});
|
||
});
|
||
|
||
// divider
|
||
t.Cell().Border(0).Text("");
|
||
|
||
// Right pane (no signature line)
|
||
t.Cell().Element(x => x.Padding(8)).Column(cc =>
|
||
{
|
||
cc.Item().Text("Completed by:").Bold();
|
||
cc.Item().PaddingTop(4).Row(r =>
|
||
{
|
||
r.ConstantItem(44).Text("Name:");
|
||
r.RelativeItem().Text(m.ItCompletedBy ?? "");
|
||
r.ConstantItem(44).Text("Date:");
|
||
r.RelativeItem().Text(F(m.ItAcceptedAt));
|
||
});
|
||
});
|
||
});
|
||
});
|
||
|
||
});
|
||
}
|
||
|
||
// Left-pane table used in Block 1 (matches your rows & borders)
|
||
void SectionB_AssetInfoTable(IContainer c, ItRequestReportModel m)
|
||
{
|
||
c.Table(t =>
|
||
{
|
||
t.ColumnsDefinition(cols =>
|
||
{
|
||
cols.RelativeColumn(2); // label
|
||
cols.RelativeColumn(2); // value box
|
||
});
|
||
|
||
void Row(string label, string value)
|
||
{
|
||
t.Cell().BorderBottom(1).Padding(6).Text(label);
|
||
t.Cell().BorderLeft(1).BorderBottom(1).Padding(3).Text(value ?? "");
|
||
}
|
||
|
||
// top row gets its own bottom borders; left cell also has right divider
|
||
Row("Asset No:", m.AssetNo);
|
||
Row("Machine ID:", m.MachineId);
|
||
Row("IP Add:", m.IpAddress);
|
||
Row("Wired Mac Add:", m.WiredMac);
|
||
Row("Wi-Fi Mac Add:", m.WifiMac);
|
||
Row("Dial-up Acc:", m.DialupAcc);
|
||
});
|
||
}
|
||
|
||
#endregion
|
||
}
|
||
}
|