1eba50cf0f
Introduces per-company reusable NCalc2 pricing formula templates for complex fabricated items (roof curbs, enclosures, welded frames). Templates support two output modes — FixedRate (formula yields a dollar amount) and SurfaceAreaSqFt (formula yields sq ft fed into the standard coating engine). Includes: - CustomItemTemplate entity, migration (AddCustomItemTemplates), IUnitOfWork repo - IsCustomFormulaItem / CustomItemTemplateId / FormulaFieldValuesJson flags on QuoteItem, JobItem, CreateQuoteItemDto; mapped in all 3 JobItemAssemblyService overloads and all existingItemsData JSON projections + pageMeta blocks - ICustomFormulaAiService / CustomFormulaAiService: Claude-powered formula generator (natural language + optional diagram image) and NCalc2 evaluator - CompanySettings CRUD endpoints: GetCustomItemTemplates, Create/Update/Delete, UploadTemplateDiagram, TemplateDiagram (blob serve), EvaluateFormula, GenerateFormulaFromAi - Company Settings "Custom Formulas" tab + cfModal + company-settings-custom-formulas.js - item-wizard.js: formula item type card, renderFormulaFields, wzFormulaRecalc (live evaluate via POST), collectStep2 formula branch, buildCardHtml / emitHiddenFields - Formula badge in Quotes/Details and Jobs/Details; AI badge gap fixed in Jobs/Details - Help article (CustomFormulaTemplates.cshtml), Help Index card, HelpController action, HelpKnowledgeBase entry; 225/225 unit tests passing Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
42 lines
1.3 KiB
C#
42 lines
1.3 KiB
C#
using AutoMapper;
|
|
using PowderCoating.Core.Entities;
|
|
using PowderCoating.Application.DTOs.Company;
|
|
|
|
namespace PowderCoating.Application.Mappings;
|
|
|
|
public class CustomItemTemplateProfile : Profile
|
|
{
|
|
public CustomItemTemplateProfile()
|
|
{
|
|
CreateMap<CustomItemTemplate, CustomItemTemplateListDto>()
|
|
.ForMember(dest => dest.FieldCount,
|
|
opt => opt.MapFrom(src => CountFields(src.FieldsJson)));
|
|
|
|
CreateMap<CustomItemTemplate, CustomItemTemplateDto>();
|
|
|
|
CreateMap<CustomItemTemplate, CustomItemTemplatePickerDto>();
|
|
|
|
CreateMap<CreateCustomItemTemplateDto, CustomItemTemplate>();
|
|
|
|
CreateMap<UpdateCustomItemTemplateDto, CustomItemTemplate>()
|
|
.ForMember(dest => dest.DiagramImagePath, opt => opt.Ignore()); // set by controller after blob upload
|
|
|
|
CreateMap<CustomItemTemplate, UpdateCustomItemTemplateDto>();
|
|
}
|
|
|
|
private static int CountFields(string fieldsJson)
|
|
{
|
|
try
|
|
{
|
|
var doc = System.Text.Json.JsonDocument.Parse(fieldsJson);
|
|
return doc.RootElement.ValueKind == System.Text.Json.JsonValueKind.Array
|
|
? doc.RootElement.GetArrayLength()
|
|
: 0;
|
|
}
|
|
catch
|
|
{
|
|
return 0;
|
|
}
|
|
}
|
|
}
|