Updated EFT creds, ZIPd archive

This commit is contained in:
Doug Macintosh
2026-03-31 10:06:25 -04:00
parent bfe37f6426
commit 2d86272a81
10 changed files with 433 additions and 147 deletions

345
_Main.cs
View File

@@ -25,21 +25,14 @@ namespace bdf
class bdf
{
public static string product = "BDF";
public static string version = "3.5.2";
public static string version = "4.0.1";
public static string fullUser = WindowsIdentity.GetCurrent().Name; // \\DOMAIN\User.Id for NTLM auth for Megatool
//EFT Upload Credentials
public static bool upload = false;
public static sftp.ConnectionDetails sshDetails = new sftp.ConnectionDetails
{
host = "dev.mft.rogers.com",
ppkFile = "BDF.Embedded.private_passphr.ppk", //Add "BDR.Embedded." to filename if embedded
passPhrase = "Rogers1!",
username = "DEV_APP_BDF",
password = "DEV_APP_BDF"
};
public static sftp.ConnectionDetails sshDetails; // mapped to either DEV or PROD servers
public static string S4LT = "Test1234";
public static Dictionary<string, int> BAN = new Dictionary<string, int> { {"LDF", 857412 }, {"WAV", 864507 }, {"SIP", 858701 } };
@@ -59,7 +52,7 @@ namespace bdf
public static bool reportappend = false;
public static string reportname = "bdf_report.txt";
public static StreamWriter reportfile = new StreamWriter(@"" + reportname, reportappend);
public static StreamWriter reportfile = new StreamWriter(new FileStream(@"" + reportname, FileMode.Create, FileAccess.Write, FileShare.Read));
public static string domain = "RCI";
public static string username = "";
@@ -161,6 +154,7 @@ namespace bdf
//outfile = new StreamWriter(@"" + logname, logappend); // defined earlier so logging works in .dll loading
outfile.AutoFlush = true;
reportfile.AutoFlush = true;
//Suppress system error text messages?
//Console.SetError(TextWriter.Null);
@@ -178,6 +172,7 @@ namespace bdf
Logger.Log("--- call (613)697-9178 for support ---");
Logger.Log(product, "INIT: Tool version {0} initiated {1}", version, DateTime.Now);
Logger.Log(product, "USER: Operated by: {0}", fullUser);
// ***MAIN -------------------------------------------------------------------------------------------------------------------------------
@@ -1196,6 +1191,8 @@ namespace bdf
}
//Now it is safe to dump out BDF files as we modified the custom invoice on tab2
Dictionary<string, MemoryStream> bdfDossier = new Dictionary<string, MemoryStream> { };
MemoryStream bdf_as_ms = new MemoryStream(); //keep a copy of the BDF in case we need to add to an archive MAR26
{
// Output BDF to ./ if not uploading
@@ -1210,11 +1207,6 @@ namespace bdf
Logger.Log(task, "SUMM> {0} Detailed bill lines added. Monthly totals MRR={1:N2} NRC={2:N2} before taxes", (bdf2.LastDataRow - 1), bdf1[2, 6].Value, bdf1[2, 7].Value);
//string fileTraceable = output_path + bdf.filename.Split('.')[0] + traceable + ".xlsx";
if (!FileIsWritable(svc_path + fileTraceable)) return;
//clear older versions of same month
DeleteFilesByPrefix(svc_path + fileTraceable, 7); // use length of 12 to only clear same billing period files.
ExcelDocumentProperties edp = new ExcelDocumentProperties { };
edp.Title = "BDF " + task + " Detail";
edp.Subject = task + " Billing Detail File";
@@ -1223,8 +1215,20 @@ namespace bdf
edp.ApplyTo(workbook);
workbook.SaveToFile(svc_path + fileTraceable, ExcelVersion.Version2016);
Logger.Log(0, "Excel file populated! ({0})", svc_path + fileTraceable);
//Store output docs as memorystreams and deal with them all at once
try
{
workbook.SaveToStream(bdf_as_ms);
}
catch (Exception e)
{
Logger.Log(" BDF failed to streamify. ({0})", e.Message);
return;
}
bdfDossier.Add(fileTraceable.Substring(upload ? 4 : 2), bdf_as_ms); // remove TSK\ from start
//Logger.Log(0, "Excel file populated! ({0})", svc_path + fileTraceable);
Logger.Log(0, "Excel file populated! ({0})", fileTraceable.Substring(upload ? 4 : 2));
}
catch (Exception e)
{
@@ -1233,42 +1237,6 @@ namespace bdf
Logger.Log(0, "Please close the workbook ({0}) if you currently have it open in Excel and then retry.", traceable);
}
// are we uploading to EFT SFTP server?
if (upload)
{
Logger.Log(0, " Initiating {0}-BDF upload to EFT server...", task);
try
{
using (var ms = new MemoryStream())
{
try
{
workbook.SaveToStream(ms);
}
catch (Exception e)
{
Logger.Log(" BDF failed to format for SFTP. ({0})", e.Message);
return;
}
try
{
sftp.Upload_Stream(ms, "Outbox" + Path.DirectorySeparatorChar + fileTraceable, sshDetails);
}
catch (Exception e)
{
Logger.Log(0, "BDF SFTP Upload Exception: {0}:{1}", e.Message, e.InnerException.Message);
return;
}
//Logger.Log(" BDF uploaded.");
}
}
catch (Exception e)
{
Logger.Log(0, "BDF SFTP Upload Exception: {0}:{1}", e.Message, e.InnerException.Message);
return;
}
}
}
// Hold memorystream copies of each PDF invoice created for the ZIP/SAVE and SFTP process(es): filename, ms
@@ -1365,11 +1333,10 @@ namespace bdf
InvoiceCell icArg = SIP ? sip : ic; // pick the correct InvoiceCell to pass to customInvoice
using (MemoryStream ms = PDF.customInvoiceAsMS_taxes(ref Invoice, ref icArg)) // now pass ic, so we can access ic.TX dictionary
//using (MemoryStream ms = PDF.customInvoiceAsMS(ref Invoice))
{
if (SIP)
Logger.Log(task, "INFO: PO# {0} Creating INVOICE: MRR={1:0.00} NRC={2:0.00} Total_charges= ${3:0.00}", PO.ElementAt(i).Key, sip.Data_Services, sip.Taxes, sip.Total_Charges);
string PDF_path = "_INV_" + current.ToString() + (SIP ? (String.Format("_{0}", PO.ElementAt(i).Key)) : "") + traceable; //"." + Path.DirectorySeparatorChar;
string PDF_path = task.ToUpper() + "_INV_" + current.ToString() + (SIP ? (String.Format("_{0}", PO.ElementAt(i).Key)) : "") + traceable; //"." + Path.DirectorySeparatorChar;
ms.Position = 0;
try
@@ -1380,17 +1347,17 @@ namespace bdf
}
catch (Exception e)
{
Logger.Log(0, "Error Invoice SFTP upload", e.Message);
Logger.Log(0, "Error Invoice dossier addition", e.Message);
}
Logger.Log(0, "PDF file populated! ({0})", PDF_path + ".pdf");
}
Invoice.Clear();
}
//Now we have a Dossier of all PDF invoices, if we are compressing them, then build zip as memorystream and remove all original PDFs from Dossier
Logger.Log(2, "We have {0} invoice PDFs prepared", invoiceDossier.Count);
//Setup ZIP archive if desired (bool archive=true)
//Setup ZIP archive if desired (bool archive=true)
if (SIP && archive)
{
byte[] zip;
@@ -1426,79 +1393,236 @@ namespace bdf
}
zip = zipMS.ToArray();
}
// Now clear the dossier and replace with the single zip archive file
foreach (var ms in invoiceDossier.Values)
ms?.Dispose();
invoiceDossier.Clear();
// Re-Add the zip to the dossier
string fname = "_INV_" + current.ToString() + traceable + ".zip";
Logger.Log(2, "Adding {0} to Dossier", fname);
invoiceDossier.Add(fname, new MemoryStream(zip));
}
// Now we either have a Dictionary of PDFs, or one with a single ZIP file
// If we aren't uploading then we just dump the file locally
bool deleted = false;
// Add in all invoice stream(s) to BDF Dossier
foreach (var file in invoiceDossier)
{
try
{
//PDF.customInvoiceSaveFile(task, file.Key, file.Value);
bdfDossier.Add(file.Key, file.Value);
Logger.Log(2, " - adding invoice file: {0}", file.Key);
}
// Now we save or upload all files generated
List<string> cleared_files = new List<string> { }; // tracks which file prefix have been deleted
file.Value.Position = 0;
if (!upload)
{
foreach (var file in bdfDossier)
{
Logger.Log(2, " + processing file: {0}", file.Key);
string srv_path = bdf.upload ? bdf.base_path + "BDF_Archive" + Path.DirectorySeparatorChar : "";
string file_name = (bdf.upload ? task.ToUpper() : ".") + Path.DirectorySeparatorChar + task.ToUpper() + file.Key;
string file_name = (bdf.upload ? task.ToUpper() : ".") + Path.DirectorySeparatorChar + file.Key;
string prefix = file.Key.Substring(0, 14);
if (!FileIsWritable(srv_path + file_name)) return;
// clear older versions
if (!deleted)
{
DeleteFilesByPrefix(srv_path + file_name, 7); // use length of 12 to only clear same billing period files.
deleted = true;
}
File.WriteAllBytes(srv_path + file_name, file.Value.ToArray());
Logger.Log(0, "Invoice written! ({0})", srv_path + file_name);
}
catch (Exception e)
{
Logger.Log(0, "Error Saving Invoice(s) to File", e.Message);
}
if (upload)
try
{
file.Value.Position = 0;
string file_name = task.ToUpper() + Path.DirectorySeparatorChar + task.ToUpper() + file.Key;
if (!FileIsWritable(srv_path + file_name)) return;
if (!cleared_files.Contains(prefix))
{
Logger.Log(0, " Initiating {0}-INV upload to EFT server...", task);
try
{
try
{
sftp.Upload_Stream(file.Value, "Outbox" + Path.DirectorySeparatorChar + file_name, bdf.sshDetails);
}
catch (Exception e)
{
Logger.Log(0, "Invoice SFTP Upload Exception: {0}:{1}", e.Message, e.InnerException.Message);
return;
}
}
catch (Exception e)
{
Logger.Log(0, "INVSFTP Upload Exception: {0}:{1}", e.Message, e.InnerException.Message);
return;
}
cleared_files.Add(prefix);
Logger.Log(2, " - clearing prefix: {0}", prefix);
DeleteFilesByPrefix(srv_path + file_name, 16); // this should clear any previous files from the same year/month
}
}
catch (Exception e)
{
Logger.Log(0, "Error Invoice SFTP upload", e.Message);
Logger.Log(0, "Error Clearing Files: {0}", e.Message);
}
}
// Cleanup stuff
CXLFile.S_ServiceOrders.RemoveRange(0, CXLFile.S_ServiceOrders.Count);
try
{
file.Value.Position = 0;
File.WriteAllBytes(srv_path + file_name, file.Value.ToArray());
Logger.Log(0, " > file written: ({0})", srv_path + file_name);
}
catch (Exception e)
{
Logger.Log(0, "Error Saving Files: {0}", e.Message);
}
}
}
else // UPLOAD : we are uploading via SFTP, and creating a ZIP archive on Sharepoint MAR29
{
try
{
Logger.Log(0, "Initiating [{0}] upload to EFT Server...", task);
try
{
sftp.Upload_DictStream(bdfDossier, task.ToUpper(), sshDetails);
}
catch (Exception e)
{
Logger.Log(0, "SFTP Upload Exception: {0}:{1}", e.Message, e.InnerException.Message);
return;
}
}
catch (Exception e)
{
Logger.Log(0, "Error SFTP upload {0}:{1}", e.Message, e.InnerException.Message);
}
//Setup ZIP file for Archive folder
byte[] zip;
//using (FileStream zipFS = new FileStream("test.zip", FileMode.Create))
using (MemoryStream zipMS = new MemoryStream())
{
using (ZipArchive archive = new ZipArchive(zipMS, ZipArchiveMode.Create, leaveOpen: false))
{
foreach (var entry in bdfDossier)
{
string fileName = entry.Key;
MemoryStream fileStream = entry.Value;
Logger.Log(2, " adding {0} to ZIP archive", fileName);
// Create a new entry in the zip archive
ZipArchiveEntry zipEntry = archive.CreateEntry(fileName);
// Open the entry stream to write data into the zip file
// 'using' ensures the entry stream is disposed after writing.
using (Stream entryStream = zipEntry.Open())
{
// Ensure the source stream is at the beginning before copying
if (fileStream.CanSeek && fileStream.Position != 0)
{
fileStream.Seek(0, SeekOrigin.Begin);
}
// Copy the contents from the source MemoryStream to the destination ZipArchiveEntry stream
fileStream.CopyTo(entryStream);
}
//invoiceDossier.Remove(entry.Key);
}
//Add BDF Tool Run User report to archive
reportfile.Close();
ZipArchiveEntry report = archive.CreateEntry("Report.txt");
using (Stream reportStream = report.Open())
{
try
{
using (FileStream fileStream = new FileStream(reportname, FileMode.Open, FileAccess.Read))
{
if (fileStream.CanSeek && fileStream.Position != 0)
{
//Console.WriteLine("c");
fileStream.Seek(0, SeekOrigin.Begin);
}
//Console.WriteLine("d");
fileStream.CopyTo(reportStream);
}
}
catch (FileNotFoundException ex)
{
Console.Error.WriteLine($"File not found: {ex.FileName}");
}
catch (UnauthorizedAccessException ex)
{
Console.Error.WriteLine("Access denied to file.{0}", ex.Message);
}
catch (IOException ex)
{
Console.Error.WriteLine($"I/O error: {ex.Message}");
}
catch (Exception ex)
{
// fallback (optional, depending on your policy)
Console.Error.WriteLine($"Unexpected error: {ex.Message}");
}
}
//Re-enable reportfile for rest of run, this time as append.
reportfile = new StreamWriter(new FileStream(@"" + reportname, FileMode.Append, FileAccess.Write, FileShare.Read));
reportfile.AutoFlush = true;
}
zip = zipMS.ToArray();
}
// Now write out the single archive file
string srv_path = bdf.base_path + "BDF_Archive" + Path.DirectorySeparatorChar + task.ToUpper() + Path.DirectorySeparatorChar;
string fname = task.ToUpper() + "_Archive_" + current.ToString() + traceable + ".zip";
Logger.Log(0, "Adding {0} to Archive Folder", fname);
try
{
if (!FileIsWritable(srv_path + fname)) return;
//Logger.Log(0, "..check for deletion {0}/{1}", srv_path + fname, (srv_path + fname).Length);
DeleteFilesByPrefix(srv_path + fname, (srv_path + fname).Length); // this should clear any previous files from the same user on the same day
}
catch (Exception e)
{
Logger.Log(0, "Error Clearing Archive Files: {0}", e.Message);
}
try
{
File.WriteAllBytes(srv_path + fname, zip);
//Logger.Log(0, " > archive written: ({0})", srv_path + fname);
Logger.Log(0, " > archive written: ({0})", fname);
}
catch (Exception e)
{
Logger.Log(0, "Error Saving Archive Files: {0}", e.Message);
}
}
// Cleanup stuff
try
{
foreach (var ms in invoiceDossier.Values)
ms?.Dispose();
invoiceDossier.Clear();
cleared_files.Clear();
}
catch (Exception e)
{
Logger.Log(0, "Error Disposing 1: {0}", e.Message);
}
try
{
foreach (var ms in bdfDossier.Values)
ms?.Dispose();
bdfDossier.Clear();
}
catch (Exception e)
{
Logger.Log(0, "Error Disposing 2: {0}", e.Message);
}
try
{
foreach (var wb in CXLFile.S_ServiceOrders)
wb?.Dispose();
//CXLFile.S_ServiceOrders.RemoveRange(0, CXLFile.S_ServiceOrders.Count);
CXLFile.S_ServiceOrders.Clear();
}
catch (Exception e)
{
Logger.Log(0, "Error Disposing 3: {0}", e.Message);
}
} // end of MAIN()
Logger.Log("All done! Have a Great Day :) ");
Logger.Log(product, "TERM: Successful Completion at {0}", DateTime.Now);
outfile.Close();
reportfile.Close();
//reportfile.Close();
} // end of to-do loop
@@ -2015,6 +2139,15 @@ namespace bdf
Logger.Log(0, $"Error: {ex.Message}");
}
}
public static void DisposeAndClear<T>(ICollection<T> collection) where T : IDisposable
{
foreach (var item in collection)
{
item.Dispose();
}
collection.Clear();
}
}
public class ExcelDocumentProperties