Fix preferred powder selection and expand company settings export
- customer-details.js: encode double quotes in JSON.stringify output as " so onclick attributes parse correctly when powder names contain double quotes - ToolsController: add company_settings CSV to ExportAllCsv ZIP archive (was missing entirely) - ToolsController: add ~30 missing fields to GenerateCompanySettingsCsv — AccountingMethod, timeclock settings, all shop capability/blast/coat rate fields, complexity surcharge percents, pricing mode, invoice number prefix, email-from fields, per-event notification flags, payment reminder settings, document accent colors/terms/footer notes, kiosk intake output - Update GenerateCompanySettingsTemplate to match so import template stays in sync with export Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -2092,6 +2092,27 @@ public class ToolsController : Controller
|
||||
{
|
||||
await writer.WriteAsync(purchaseOrdersCsv);
|
||||
}
|
||||
|
||||
// 16. Company Settings
|
||||
var settingsCompany = await _unitOfWork.Companies.GetByIdAsync(companyId.Value, false,
|
||||
c => c.OperatingCosts, c => c.Preferences, c => c.PricingTiers);
|
||||
if (settingsCompany != null)
|
||||
{
|
||||
var settingsJobStatuses = await _unitOfWork.JobStatusLookups.FindAsync(s => s.CompanyId == companyId.Value);
|
||||
var settingsJobPriorities = await _unitOfWork.JobPriorityLookups.FindAsync(p => p.CompanyId == companyId.Value);
|
||||
var settingsQuoteStatuses = await _unitOfWork.QuoteStatusLookups.FindAsync(s => s.CompanyId == companyId.Value);
|
||||
var settingsInventoryCategories = await _unitOfWork.InventoryCategoryLookups.FindAsync(c => c.CompanyId == companyId.Value);
|
||||
var settingsApptStatuses = await _unitOfWork.AppointmentStatusLookups.FindAsync(s => s.CompanyId == companyId.Value);
|
||||
var settingsApptTypes = await _unitOfWork.AppointmentTypeLookups.FindAsync(t => t.CompanyId == companyId.Value);
|
||||
var settingsCsv = GenerateCompanySettingsCsv(settingsCompany, settingsJobStatuses, settingsJobPriorities,
|
||||
settingsQuoteStatuses, settingsInventoryCategories, settingsApptStatuses, settingsApptTypes);
|
||||
var settingsEntry = archive.CreateEntry($"company_settings_{timestamp}.csv");
|
||||
using (var entryStream = settingsEntry.Open())
|
||||
using (var writer = new System.IO.StreamWriter(entryStream))
|
||||
{
|
||||
await writer.WriteAsync(settingsCsv);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
memoryStream.Position = 0;
|
||||
@@ -2785,23 +2806,46 @@ public class ToolsController : Controller
|
||||
sb.AppendLine("State,");
|
||||
sb.AppendLine("ZipCode,");
|
||||
sb.AppendLine("TimeZone,America/New_York");
|
||||
sb.AppendLine("AccountingMethod,Accrual");
|
||||
sb.AppendLine("TimeclockEnabled,true");
|
||||
sb.AppendLine("TimeclockAllowMultiplePunchesPerDay,true");
|
||||
sb.AppendLine("TimeclockAutoClockOutHours,");
|
||||
sb.AppendLine();
|
||||
|
||||
// Operating Costs
|
||||
sb.AppendLine("[Operating Costs]");
|
||||
sb.AppendLine("StandardLaborRate,65.00");
|
||||
sb.AppendLine("LaborCostPerHour,");
|
||||
sb.AppendLine("AdditionalCoatLaborPercent,30");
|
||||
sb.AppendLine("OvenOperatingCostPerHour,25.00");
|
||||
sb.AppendLine("DefaultOvenCycleMinutes,45");
|
||||
sb.AppendLine("SandblasterCostPerHour,35.00");
|
||||
sb.AppendLine("CoatingBoothCostPerHour,30.00");
|
||||
sb.AppendLine("PowderCoatingCostPerSqFt,0.50");
|
||||
sb.AppendLine("PricingMode,MarkupOnMaterial");
|
||||
sb.AppendLine("GeneralMarkupPercentage,35");
|
||||
sb.AppendLine("TargetMarginPercent,0");
|
||||
sb.AppendLine("TaxPercent,8.5");
|
||||
sb.AppendLine("ShopSuppliesRate,5");
|
||||
sb.AppendLine("RushChargeType,Percentage");
|
||||
sb.AppendLine("RushChargePercentage,25");
|
||||
sb.AppendLine("RushChargeFixedAmount,0");
|
||||
sb.AppendLine("ShopMinimumCharge,50.00");
|
||||
sb.AppendLine("ComplexitySimplePercent,0");
|
||||
sb.AppendLine("ComplexityModeratePercent,5");
|
||||
sb.AppendLine("ComplexityComplexPercent,15");
|
||||
sb.AppendLine("ComplexityExtremePercent,25");
|
||||
sb.AppendLine("ShopCapabilityTier,Small");
|
||||
sb.AppendLine("BlastSetupType,SiphonCabinet");
|
||||
sb.AppendLine("CompressorCfm,0");
|
||||
sb.AppendLine("BlastNozzleSize,4");
|
||||
sb.AppendLine("PrimaryBlastSubstrate,Mixed");
|
||||
sb.AppendLine("BlastRateSqFtPerHourOverride,");
|
||||
sb.AppendLine("CoatingGunType,Corona");
|
||||
sb.AppendLine("CoatingRateSqFtPerHourOverride,");
|
||||
sb.AppendLine("MonthlyRent,0");
|
||||
sb.AppendLine("MonthlyUtilities,0");
|
||||
sb.AppendLine("MonthlyBillableHours,160");
|
||||
sb.AppendLine();
|
||||
|
||||
// Preferences
|
||||
@@ -2813,16 +2857,22 @@ public class ToolsController : Controller
|
||||
sb.AppendLine("DefaultQuoteValidityDays,30");
|
||||
sb.AppendLine("QuoteNumberPrefix,QT");
|
||||
sb.AppendLine("JobNumberPrefix,JOB");
|
||||
sb.AppendLine("InvoiceNumberPrefix,INV");
|
||||
sb.AppendLine("UseMetricSystem,false");
|
||||
sb.AppendLine("DefaultJobPriority,Normal");
|
||||
sb.AppendLine("RequireCustomerPO,false");
|
||||
sb.AppendLine("AllowCustomerApproval,true");
|
||||
sb.AppendLine("DefaultTurnaroundDays,7");
|
||||
sb.AppendLine("EmailFromAddress,");
|
||||
sb.AppendLine("EmailFromName,");
|
||||
sb.AppendLine("EmailNotificationsEnabled,true");
|
||||
sb.AppendLine("NotifyOnNewJob,true");
|
||||
sb.AppendLine("NotifyOnNewQuote,true");
|
||||
sb.AppendLine("NotifyOnJobStatusChange,true");
|
||||
sb.AppendLine("NotifyOnQuoteApproval,true");
|
||||
sb.AppendLine("NotifyOnPaymentReceived,true");
|
||||
sb.AppendLine("PaymentRemindersEnabled,false");
|
||||
sb.AppendLine("PaymentReminderDays,7,14,30");
|
||||
sb.AppendLine("QuoteExpiryWarningDays,3");
|
||||
sb.AppendLine("DueDateWarningDays,2");
|
||||
sb.AppendLine("MaintenanceAlertDays,7");
|
||||
@@ -2831,6 +2881,16 @@ public class ToolsController : Controller
|
||||
sb.AppendLine("LogRetentionDays,90");
|
||||
sb.AppendLine("AutoArchiveJobsDays,365");
|
||||
sb.AppendLine("DeletedRecordRetentionDays,30");
|
||||
sb.AppendLine("QtAccentColor,#374151");
|
||||
sb.AppendLine("QtDefaultTerms,");
|
||||
sb.AppendLine("QtFooterNote,");
|
||||
sb.AppendLine("InAccentColor,#374151");
|
||||
sb.AppendLine("InDefaultTerms,");
|
||||
sb.AppendLine("InFooterNote,");
|
||||
sb.AppendLine("WoAccentColor,#374151");
|
||||
sb.AppendLine("WoTerms,");
|
||||
sb.AppendLine("KioskIntakeOutput,Quote");
|
||||
sb.AppendLine("MigratingFromQuickBooks,false");
|
||||
sb.AppendLine();
|
||||
|
||||
// Pricing Tiers
|
||||
@@ -2925,6 +2985,10 @@ public class ToolsController : Controller
|
||||
sb.AppendLine($"State,{EscapeCsv(company.State)}");
|
||||
sb.AppendLine($"ZipCode,{EscapeCsv(company.ZipCode)}");
|
||||
sb.AppendLine($"TimeZone,{EscapeCsv(company.TimeZone)}");
|
||||
sb.AppendLine($"AccountingMethod,{company.AccountingMethod}");
|
||||
sb.AppendLine($"TimeclockEnabled,{company.TimeclockEnabled.ToString().ToLower()}");
|
||||
sb.AppendLine($"TimeclockAllowMultiplePunchesPerDay,{company.TimeclockAllowMultiplePunchesPerDay.ToString().ToLower()}");
|
||||
sb.AppendLine($"TimeclockAutoClockOutHours,{company.TimeclockAutoClockOutHours?.ToString() ?? ""}");
|
||||
sb.AppendLine();
|
||||
|
||||
// Operating Costs
|
||||
@@ -2933,18 +2997,37 @@ public class ToolsController : Controller
|
||||
var costs = company.OperatingCosts;
|
||||
sb.AppendLine("[Operating Costs]");
|
||||
sb.AppendLine($"StandardLaborRate,{costs.StandardLaborRate}");
|
||||
sb.AppendLine($"LaborCostPerHour,{costs.LaborCostPerHour?.ToString() ?? ""}");
|
||||
sb.AppendLine($"AdditionalCoatLaborPercent,{costs.AdditionalCoatLaborPercent}");
|
||||
sb.AppendLine($"OvenOperatingCostPerHour,{costs.OvenOperatingCostPerHour}");
|
||||
sb.AppendLine($"DefaultOvenCycleMinutes,{costs.DefaultOvenCycleMinutes}");
|
||||
sb.AppendLine($"SandblasterCostPerHour,{costs.SandblasterCostPerHour}");
|
||||
sb.AppendLine($"CoatingBoothCostPerHour,{costs.CoatingBoothCostPerHour}");
|
||||
sb.AppendLine($"PowderCoatingCostPerSqFt,{costs.PowderCoatingCostPerSqFt}");
|
||||
sb.AppendLine($"PricingMode,{costs.PricingMode}");
|
||||
sb.AppendLine($"GeneralMarkupPercentage,{costs.GeneralMarkupPercentage}");
|
||||
sb.AppendLine($"TargetMarginPercent,{costs.TargetMarginPercent}");
|
||||
sb.AppendLine($"TaxPercent,{costs.TaxPercent}");
|
||||
sb.AppendLine($"ShopSuppliesRate,{costs.ShopSuppliesRate}");
|
||||
sb.AppendLine($"RushChargeType,{EscapeCsv(costs.RushChargeType)}");
|
||||
sb.AppendLine($"RushChargePercentage,{costs.RushChargePercentage}");
|
||||
sb.AppendLine($"RushChargeFixedAmount,{costs.RushChargeFixedAmount}");
|
||||
sb.AppendLine($"ShopMinimumCharge,{costs.ShopMinimumCharge}");
|
||||
sb.AppendLine($"ComplexitySimplePercent,{costs.ComplexitySimplePercent}");
|
||||
sb.AppendLine($"ComplexityModeratePercent,{costs.ComplexityModeratePercent}");
|
||||
sb.AppendLine($"ComplexityComplexPercent,{costs.ComplexityComplexPercent}");
|
||||
sb.AppendLine($"ComplexityExtremePercent,{costs.ComplexityExtremePercent}");
|
||||
sb.AppendLine($"ShopCapabilityTier,{costs.ShopCapabilityTier}");
|
||||
sb.AppendLine($"BlastSetupType,{costs.BlastSetupType}");
|
||||
sb.AppendLine($"CompressorCfm,{costs.CompressorCfm}");
|
||||
sb.AppendLine($"BlastNozzleSize,{costs.BlastNozzleSize}");
|
||||
sb.AppendLine($"PrimaryBlastSubstrate,{costs.PrimaryBlastSubstrate}");
|
||||
sb.AppendLine($"BlastRateSqFtPerHourOverride,{costs.BlastRateSqFtPerHourOverride?.ToString() ?? ""}");
|
||||
sb.AppendLine($"CoatingGunType,{costs.CoatingGunType}");
|
||||
sb.AppendLine($"CoatingRateSqFtPerHourOverride,{costs.CoatingRateSqFtPerHourOverride?.ToString() ?? ""}");
|
||||
sb.AppendLine($"MonthlyRent,{costs.MonthlyRent}");
|
||||
sb.AppendLine($"MonthlyUtilities,{costs.MonthlyUtilities}");
|
||||
sb.AppendLine($"MonthlyBillableHours,{costs.MonthlyBillableHours}");
|
||||
sb.AppendLine();
|
||||
}
|
||||
|
||||
@@ -2960,16 +3043,22 @@ public class ToolsController : Controller
|
||||
sb.AppendLine($"DefaultQuoteValidityDays,{prefs.DefaultQuoteValidityDays}");
|
||||
sb.AppendLine($"QuoteNumberPrefix,{EscapeCsv(prefs.QuoteNumberPrefix)}");
|
||||
sb.AppendLine($"JobNumberPrefix,{EscapeCsv(prefs.JobNumberPrefix)}");
|
||||
sb.AppendLine($"InvoiceNumberPrefix,{EscapeCsv(prefs.InvoiceNumberPrefix)}");
|
||||
sb.AppendLine($"UseMetricSystem,{prefs.UseMetricSystem.ToString().ToLower()}");
|
||||
sb.AppendLine($"DefaultJobPriority,{EscapeCsv(prefs.DefaultJobPriority)}");
|
||||
sb.AppendLine($"RequireCustomerPO,{prefs.RequireCustomerPO.ToString().ToLower()}");
|
||||
sb.AppendLine($"AllowCustomerApproval,{prefs.AllowCustomerApproval.ToString().ToLower()}");
|
||||
sb.AppendLine($"DefaultTurnaroundDays,{prefs.DefaultTurnaroundDays}");
|
||||
sb.AppendLine($"EmailFromAddress,{EscapeCsv(prefs.EmailFromAddress)}");
|
||||
sb.AppendLine($"EmailFromName,{EscapeCsv(prefs.EmailFromName)}");
|
||||
sb.AppendLine($"EmailNotificationsEnabled,{prefs.EmailNotificationsEnabled.ToString().ToLower()}");
|
||||
sb.AppendLine($"NotifyOnNewJob,{prefs.NotifyOnNewJob.ToString().ToLower()}");
|
||||
sb.AppendLine($"NotifyOnNewQuote,{prefs.NotifyOnNewQuote.ToString().ToLower()}");
|
||||
sb.AppendLine($"NotifyOnJobStatusChange,{prefs.NotifyOnJobStatusChange.ToString().ToLower()}");
|
||||
sb.AppendLine($"NotifyOnQuoteApproval,{prefs.NotifyOnQuoteApproval.ToString().ToLower()}");
|
||||
sb.AppendLine($"NotifyOnPaymentReceived,{prefs.NotifyOnPaymentReceived.ToString().ToLower()}");
|
||||
sb.AppendLine($"PaymentRemindersEnabled,{prefs.PaymentRemindersEnabled.ToString().ToLower()}");
|
||||
sb.AppendLine($"PaymentReminderDays,{EscapeCsv(prefs.PaymentReminderDays)}");
|
||||
sb.AppendLine($"QuoteExpiryWarningDays,{prefs.QuoteExpiryWarningDays}");
|
||||
sb.AppendLine($"DueDateWarningDays,{prefs.DueDateWarningDays}");
|
||||
sb.AppendLine($"MaintenanceAlertDays,{prefs.MaintenanceAlertDays}");
|
||||
@@ -2978,6 +3067,16 @@ public class ToolsController : Controller
|
||||
sb.AppendLine($"LogRetentionDays,{prefs.LogRetentionDays}");
|
||||
sb.AppendLine($"AutoArchiveJobsDays,{prefs.AutoArchiveJobsDays}");
|
||||
sb.AppendLine($"DeletedRecordRetentionDays,{prefs.DeletedRecordRetentionDays}");
|
||||
sb.AppendLine($"QtAccentColor,{EscapeCsv(prefs.QtAccentColor)}");
|
||||
sb.AppendLine($"QtDefaultTerms,{EscapeCsv(prefs.QtDefaultTerms)}");
|
||||
sb.AppendLine($"QtFooterNote,{EscapeCsv(prefs.QtFooterNote)}");
|
||||
sb.AppendLine($"InAccentColor,{EscapeCsv(prefs.InAccentColor)}");
|
||||
sb.AppendLine($"InDefaultTerms,{EscapeCsv(prefs.InDefaultTerms)}");
|
||||
sb.AppendLine($"InFooterNote,{EscapeCsv(prefs.InFooterNote)}");
|
||||
sb.AppendLine($"WoAccentColor,{EscapeCsv(prefs.WoAccentColor)}");
|
||||
sb.AppendLine($"WoTerms,{EscapeCsv(prefs.WoTerms)}");
|
||||
sb.AppendLine($"KioskIntakeOutput,{EscapeCsv(prefs.KioskIntakeOutput)}");
|
||||
sb.AppendLine($"MigratingFromQuickBooks,{prefs.MigratingFromQuickBooks.ToString().ToLower()}");
|
||||
sb.AppendLine();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user