@archerjessop/utilities 7.14.0 → 7.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{equityPercentFromDebt as e}from"../financial/calculations.js";function mapPropertyType(e){return{assisted:"assisted",business:"business",mixed_use:"mixed_use",multifamily:"mfr",rv_park:"rv_park",str:"str"}[e]||"mfr"}function createExportObjectCore(t,r={}){const{currentDownPaymentPercent:n,currentInterestRateType:a="dscr_residential",currentMortgages:o=[],currentPriceDiscount:i=0,currentPropertyType:c="str",equitySource:
|
|
1
|
+
import{equityPercentFromDebt as e}from"../financial/calculations.js";function mapPropertyType(e){return{assisted:"assisted",business:"business",mixed_use:"mixed_use",multifamily:"mfr",rv_park:"rv_park",str:"str"}[e]||"mfr"}function createExportObjectCore(t,r={}){const{currentDownPaymentPercent:n,currentInterestRateType:a="dscr_residential",currentMortgages:o=[],currentPriceDiscount:i=0,currentPropertyType:c="str",equitySource:u="scraped",estimatedMortgageBalance:s=null,isUsingEstimatedCapRate:p=!1,noi:d=null,numberOfUnits:l=4,priceWasDefaulted:m=!1,windowLocation:f=""}=r;if(m)return null;const y={};if(t.name&&"Property Details"!==t.name&&"Not found"!==t.name&&(y.address=t.name),t.capRate&&"Loading..."!==t.capRate&&"Not found"!==t.capRate){const e=t.capRate.match(/[\d.]+/);if(e){const r=parseFloat(e[0]);t.capRate.includes("%")||r>1?y.capRate=Math.round(r/100*1e6)/1e6:y.capRate=Math.round(1e6*r)/1e6}}if(y.capRateSource=p?"estimated":"scraped",t.contact&&"Not found"!==t.contact&&(y.contact=t.contact),t.listingDate&&"Not found"!==t.listingDate&&(y.dateListed=t.listingDate),t.price&&"Loading..."!==t.price&&"Not found"!==t.price){const e=t.price.match(/[\d,]+/);e&&(y.price=Math.round(parseFloat(e[0].replace(/,/g,""))))}if(Number.isFinite(d)&&d>0&&(y.noi=Math.round(d)),void 0!==n&&(y.downPaymentPercent=Math.round(n/100*1e6)/1e6),Number.isFinite(y.price)&&y.price>0){const t=e(y.price,s),r=Math.max(0,Math.min(1,t));y.equityPercent=Math.round(1e6*r)/1e6}y.equitySource=u,Number.isFinite(s)&&(y.estimatedMortgageBalance=Math.round(s)),Array.isArray(o)&&o.length>0&&(y.currentMortgages=JSON.stringify(o)),y.numberOfUnits=l,t.phone&&"Not found"!==t.phone&&(y.phone=t.phone),y.priceDiscountPercent=i>0?Math.round(i/100*1e6)/1e6:0,y.interestRateType=a,y.propertyType=mapPropertyType(c),y.url=f,console.log("exportData",y);const h={};return Object.keys(y).sort().forEach(e=>{h[e]=y[e]}),h}function calculateOriginalPrice(e,t){if(t>0){return e/(1-t/100)}return e}function convertCapRateToDecimal(e){if(!e||"Loading..."===e||"Not found"===e)return null;const t=e.match(/[\d.]+/);if(t){const r=parseFloat(t[0]);return e.includes("%")||r>1?Math.round(r/100*1e6)/1e6:Math.round(1e6*r)/1e6}return null}function formatDownPaymentPercent(e){return Math.round(e/100*1e6)/1e6}export{calculateOriginalPrice,convertCapRateToDecimal,createExportObjectCore,formatDownPaymentPercent,mapPropertyType};
|
|
2
2
|
//# sourceMappingURL=export-logic.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"export-logic.js","sources":["../../src/export/export-logic.js"],"sourcesContent":["import { equityPercentFromDebt } from \"../financial/calculations.js\";\r\n\r\n// Map the on-screen property type to the dashboard's DB enum. Only \"multifamily\" -> \"mfr\"\r\n// actually differs; the rest pass through. Mirrors property-dashboard/validation/property.js\r\n// mapPropertyType (same table, same unknown -> \"mfr\" default) so the export URL carries the\r\n// real enum instead of relying on the server to convert it.\r\nexport function mapPropertyType(type) {\r\n const typeMap = {\r\n assisted: \"assisted\",\r\n business: \"business\",\r\n mixed_use: \"mixed_use\",\r\n multifamily: \"mfr\",\r\n rv_park: \"rv_park\",\r\n str: \"str\",\r\n };\r\n return typeMap[type] || \"mfr\";\r\n}\r\n\r\n// Pure business logic for data export - no DOM, no Chrome APIs.\r\n// Returns null to REFUSE export when the price was defaulted (no real price found):\r\n// a fabricated price would flow into NOI and silently land garbage in the dashboard.\r\nexport function createExportObjectCore(data, options = {}) {\r\n const {\r\n currentDownPaymentPercent,\r\n currentInterestRateType = \"dscr_residential\",\r\n currentMortgages = [],\r\n currentPriceDiscount = 0,\r\n currentPropertyType = \"str\",\r\n equitySource = \"scraped\",\r\n estimatedMortgageBalance = null,\r\n isUsingEstimatedCapRate = false,\r\n noi = null,\r\n numberOfUnits = 4,\r\n priceWasDefaulted = false,\r\n windowLocation = \"\",\r\n } = options;\r\n\r\n if (priceWasDefaulted) return null;\r\n\r\n const exportData = {};\r\n\r\n // 1. Address\r\n if (data.name && data.name !== \"Property Details\" && data.name !== \"Not found\") {\r\n exportData.address = data.name;\r\n }\r\n\r\n // 2. Cap Rate - convert to decimal\r\n if (data.capRate && data.capRate !== \"Loading...\" && data.capRate !== \"Not found\") {\r\n const capMatch = data.capRate.match(/[\\d.]+/);\r\n if (capMatch) {\r\n const numericValue = parseFloat(capMatch[0]);\r\n\r\n // If the original string contains %, it's a percentage that needs conversion\r\n // If it's already a small decimal (< 1), it's likely already in decimal format\r\n if (data.capRate.includes(\"%\") || numericValue > 1) {\r\n // Percentage format - convert to decimal\r\n exportData.capRate = Math.round((numericValue / 100) * 1000000) / 1000000;\r\n } else {\r\n // Already in decimal format - use as-is\r\n exportData.capRate = Math.round(numericValue * 1000000) / 1000000;\r\n }\r\n }\r\n }\r\n\r\n // 3. Cap Rate Source\r\n exportData.capRateSource = isUsingEstimatedCapRate ? \"estimated\" : \"scraped\";\r\n\r\n // 4. Contact name\r\n if (data.contact && data.contact !== \"Not found\") {\r\n exportData.contact = data.contact;\r\n }\r\n\r\n // 5. Date Listed\r\n if (data.listingDate && data.listingDate !== \"Not found\") {\r\n exportData.dateListed = data.listingDate;\r\n }\r\n\r\n // 6. Price - calculate original price if discount applied\r\n if (data.price && data.price !== \"Loading...\" && data.price !== \"Not found\") {\r\n const priceMatch = data.price.match(/[\\d,]+/);\r\n if (priceMatch) {\r\n const displayedPrice = parseFloat(priceMatch[0].replace(/,/g, \"\"));\r\n\r\n if (currentPriceDiscount > 0) {\r\n const discountDecimal = currentPriceDiscount / 100;\r\n const originalPrice = displayedPrice / (1 - discountDecimal);\r\n exportData.price = Math.round(originalPrice);\r\n } else {\r\n exportData.price = displayedPrice;\r\n }\r\n }\r\n }\r\n\r\n // 6b. NOI - the computed net operating income (additive; the dashboard stores it in the noi\r\n // column and derives the active cap rate as noi/price). The reported cap rate is carried\r\n // separately in capRate, unchanged. Omitted when no NOI was computed.\r\n if (Number.isFinite(noi) && noi > 0) {\r\n exportData.noi = Math.round(noi);\r\n }\r\n\r\n // 7. Down Payment Percent (user-controlled value)\r\n if (currentDownPaymentPercent !== undefined) {\r\n exportData.downPaymentPercent = Math.round((currentDownPaymentPercent / 100) * 1000000) / 1000000;\r\n }\r\n\r\n // 8. Equity Percent — DERIVED from scraped debt vs the export price (no debt => 100%).\r\n // Clamped to [0,1] for the dashboard's equity_percent CHECK; the live panel shows reality.\r\n if (Number.isFinite(exportData.price) && exportData.price > 0) {\r\n const equity = equityPercentFromDebt(exportData.price, estimatedMortgageBalance);\r\n const clamped = Math.max(0, Math.min(1, equity));\r\n exportData.equityPercent = Math.round(clamped * 1000000) / 1000000;\r\n }\r\n\r\n // 9. Equity Source\r\n exportData.equitySource = equitySource;\r\n\r\n // 9b. Scraped debt (additive; dashboard stores estimated_debt_balance + scraped_mortgages,\r\n // distinct from the loan_1/2/3 due-diligence slots). Omitted when there is no figure.\r\n if (Number.isFinite(estimatedMortgageBalance)) {\r\n exportData.estimatedMortgageBalance = Math.round(estimatedMortgageBalance);\r\n }\r\n if (Array.isArray(currentMortgages) && currentMortgages.length > 0) {\r\n exportData.currentMortgages = JSON.stringify(currentMortgages);\r\n }\r\n\r\n // 10. Number of Units\r\n exportData.numberOfUnits = numberOfUnits;\r\n\r\n // 11. Phone number\r\n if (data.phone && data.phone !== \"Not found\") {\r\n exportData.phone = data.phone;\r\n }\r\n\r\n // 11. Price Discount Percent\r\n if (currentPriceDiscount > 0) {\r\n exportData.priceDiscountPercent = Math.round((currentPriceDiscount / 100) * 1000000) / 1000000;\r\n } else {\r\n exportData.priceDiscountPercent = 0;\r\n }\r\n\r\n // 12. Interest Rate Type\r\n exportData.interestRateType = currentInterestRateType;\r\n\r\n // 13. Property Type - mapped to the DB enum (multifamily -> mfr; rest pass through)\r\n exportData.propertyType = mapPropertyType(currentPropertyType);\r\n\r\n // 13. URL\r\n exportData.url = windowLocation;\r\n\r\n console.log(\"exportData\", exportData);\r\n\r\n // Alphabetize keys\r\n const alphabetized = {};\r\n Object.keys(exportData).sort().forEach(key => {\r\n alphabetized[key] = exportData[key];\r\n });\r\n\r\n return alphabetized;\r\n}\r\n\r\n// Pure calculation functions\r\nexport function calculateOriginalPrice(displayedPrice, discountPercent) {\r\n if (discountPercent > 0) {\r\n const discountDecimal = discountPercent / 100;\r\n return displayedPrice / (1 - discountDecimal);\r\n }\r\n return displayedPrice;\r\n}\r\n\r\nexport function convertCapRateToDecimal(capRateString) {\r\n if (!capRateString || capRateString === \"Loading...\" || capRateString === \"Not found\") {\r\n return null;\r\n }\r\n\r\n const capMatch = capRateString.match(/[\\d.]+/);\r\n if (capMatch) {\r\n const numericValue = parseFloat(capMatch[0]);\r\n\r\n if (capRateString.includes(\"%\") || numericValue > 1) {\r\n return Math.round((numericValue / 100) * 1000000) / 1000000;\r\n } else {\r\n return Math.round(numericValue * 1000000) / 1000000;\r\n }\r\n }\r\n\r\n return null;\r\n}\r\n\r\nexport function formatDownPaymentPercent(percentage) {\r\n return Math.round((percentage / 100) * 1000000) / 1000000;\r\n}\r\n"],"names":["mapPropertyType","type","assisted","business","mixed_use","multifamily","rv_park","str","createExportObjectCore","data","options","currentDownPaymentPercent","currentInterestRateType","currentMortgages","currentPriceDiscount","currentPropertyType","equitySource","estimatedMortgageBalance","isUsingEstimatedCapRate","noi","numberOfUnits","priceWasDefaulted","windowLocation","exportData","name","address","capRate","capMatch","match","numericValue","parseFloat","includes","Math","round","capRateSource","contact","listingDate","dateListed","price","priceMatch","displayedPrice","replace","originalPrice","Number","isFinite","undefined","downPaymentPercent","equity","equityPercentFromDebt","clamped","max","min","equityPercent","Array","isArray","length","JSON","stringify","phone","priceDiscountPercent","interestRateType","propertyType","url","console","log","alphabetized","Object","keys","sort","forEach","key","calculateOriginalPrice","discountPercent","convertCapRateToDecimal","capRateString","formatDownPaymentPercent","percentage"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"export-logic.js","sources":["../../src/export/export-logic.js"],"sourcesContent":["import { equityPercentFromDebt } from \"../financial/calculations.js\";\r\n\r\n// Map the on-screen property type to the dashboard's DB enum. Only \"multifamily\" -> \"mfr\"\r\n// actually differs; the rest pass through. Mirrors property-dashboard/validation/property.js\r\n// mapPropertyType (same table, same unknown -> \"mfr\" default) so the export URL carries the\r\n// real enum instead of relying on the server to convert it.\r\nexport function mapPropertyType(type) {\r\n const typeMap = {\r\n assisted: \"assisted\",\r\n business: \"business\",\r\n mixed_use: \"mixed_use\",\r\n multifamily: \"mfr\",\r\n rv_park: \"rv_park\",\r\n str: \"str\",\r\n };\r\n return typeMap[type] || \"mfr\";\r\n}\r\n\r\n// Pure business logic for data export - no DOM, no Chrome APIs.\r\n// Returns null to REFUSE export when the price was defaulted (no real price found):\r\n// a fabricated price would flow into NOI and silently land garbage in the dashboard.\r\nexport function createExportObjectCore(data, options = {}) {\r\n const {\r\n currentDownPaymentPercent,\r\n currentInterestRateType = \"dscr_residential\",\r\n currentMortgages = [],\r\n currentPriceDiscount = 0,\r\n currentPropertyType = \"str\",\r\n equitySource = \"scraped\",\r\n estimatedMortgageBalance = null,\r\n isUsingEstimatedCapRate = false,\r\n noi = null,\r\n numberOfUnits = 4,\r\n priceWasDefaulted = false,\r\n windowLocation = \"\",\r\n } = options;\r\n\r\n if (priceWasDefaulted) return null;\r\n\r\n const exportData = {};\r\n\r\n // 1. Address\r\n if (data.name && data.name !== \"Property Details\" && data.name !== \"Not found\") {\r\n exportData.address = data.name;\r\n }\r\n\r\n // 2. Cap Rate - convert to decimal\r\n if (data.capRate && data.capRate !== \"Loading...\" && data.capRate !== \"Not found\") {\r\n const capMatch = data.capRate.match(/[\\d.]+/);\r\n if (capMatch) {\r\n const numericValue = parseFloat(capMatch[0]);\r\n\r\n // If the original string contains %, it's a percentage that needs conversion\r\n // If it's already a small decimal (< 1), it's likely already in decimal format\r\n if (data.capRate.includes(\"%\") || numericValue > 1) {\r\n // Percentage format - convert to decimal\r\n exportData.capRate = Math.round((numericValue / 100) * 1000000) / 1000000;\r\n } else {\r\n // Already in decimal format - use as-is\r\n exportData.capRate = Math.round(numericValue * 1000000) / 1000000;\r\n }\r\n }\r\n }\r\n\r\n // 3. Cap Rate Source\r\n exportData.capRateSource = isUsingEstimatedCapRate ? \"estimated\" : \"scraped\";\r\n\r\n // 4. Contact name\r\n if (data.contact && data.contact !== \"Not found\") {\r\n exportData.contact = data.contact;\r\n }\r\n\r\n // 5. Date Listed\r\n if (data.listingDate && data.listingDate !== \"Not found\") {\r\n exportData.dateListed = data.listingDate;\r\n }\r\n\r\n // 6. Price - the SCRAPED asking price. data.price is the raw page price (the true ask); the\r\n // discount is a display-only concept applied at render (getCurrentPrice), never folded into the\r\n // scrape. So export the asking as-is and carry the discount separately (step 11); the dashboard\r\n // derives offered = asking x (1 - discount). Dividing here would inflate the ask on every import.\r\n if (data.price && data.price !== \"Loading...\" && data.price !== \"Not found\") {\r\n const priceMatch = data.price.match(/[\\d,]+/);\r\n if (priceMatch) {\r\n exportData.price = Math.round(parseFloat(priceMatch[0].replace(/,/g, \"\")));\r\n }\r\n }\r\n\r\n // 6b. NOI - the computed net operating income (additive; the dashboard stores it in the noi\r\n // column and derives the active cap rate as noi/price). The reported cap rate is carried\r\n // separately in capRate, unchanged. Omitted when no NOI was computed.\r\n if (Number.isFinite(noi) && noi > 0) {\r\n exportData.noi = Math.round(noi);\r\n }\r\n\r\n // 7. Down Payment Percent (user-controlled value)\r\n if (currentDownPaymentPercent !== undefined) {\r\n exportData.downPaymentPercent = Math.round((currentDownPaymentPercent / 100) * 1000000) / 1000000;\r\n }\r\n\r\n // 8. Equity Percent — DERIVED from scraped debt vs the export price (no debt => 100%).\r\n // Clamped to [0,1] for the dashboard's equity_percent CHECK; the live panel shows reality.\r\n if (Number.isFinite(exportData.price) && exportData.price > 0) {\r\n const equity = equityPercentFromDebt(exportData.price, estimatedMortgageBalance);\r\n const clamped = Math.max(0, Math.min(1, equity));\r\n exportData.equityPercent = Math.round(clamped * 1000000) / 1000000;\r\n }\r\n\r\n // 9. Equity Source\r\n exportData.equitySource = equitySource;\r\n\r\n // 9b. Scraped debt (additive; dashboard stores estimated_debt_balance + scraped_mortgages,\r\n // distinct from the loan_1/2/3 due-diligence slots). Omitted when there is no figure.\r\n if (Number.isFinite(estimatedMortgageBalance)) {\r\n exportData.estimatedMortgageBalance = Math.round(estimatedMortgageBalance);\r\n }\r\n if (Array.isArray(currentMortgages) && currentMortgages.length > 0) {\r\n exportData.currentMortgages = JSON.stringify(currentMortgages);\r\n }\r\n\r\n // 10. Number of Units\r\n exportData.numberOfUnits = numberOfUnits;\r\n\r\n // 11. Phone number\r\n if (data.phone && data.phone !== \"Not found\") {\r\n exportData.phone = data.phone;\r\n }\r\n\r\n // 11. Price Discount Percent\r\n if (currentPriceDiscount > 0) {\r\n exportData.priceDiscountPercent = Math.round((currentPriceDiscount / 100) * 1000000) / 1000000;\r\n } else {\r\n exportData.priceDiscountPercent = 0;\r\n }\r\n\r\n // 12. Interest Rate Type\r\n exportData.interestRateType = currentInterestRateType;\r\n\r\n // 13. Property Type - mapped to the DB enum (multifamily -> mfr; rest pass through)\r\n exportData.propertyType = mapPropertyType(currentPropertyType);\r\n\r\n // 13. URL\r\n exportData.url = windowLocation;\r\n\r\n console.log(\"exportData\", exportData);\r\n\r\n // Alphabetize keys\r\n const alphabetized = {};\r\n Object.keys(exportData).sort().forEach(key => {\r\n alphabetized[key] = exportData[key];\r\n });\r\n\r\n return alphabetized;\r\n}\r\n\r\n// Pure calculation functions\r\nexport function calculateOriginalPrice(displayedPrice, discountPercent) {\r\n if (discountPercent > 0) {\r\n const discountDecimal = discountPercent / 100;\r\n return displayedPrice / (1 - discountDecimal);\r\n }\r\n return displayedPrice;\r\n}\r\n\r\nexport function convertCapRateToDecimal(capRateString) {\r\n if (!capRateString || capRateString === \"Loading...\" || capRateString === \"Not found\") {\r\n return null;\r\n }\r\n\r\n const capMatch = capRateString.match(/[\\d.]+/);\r\n if (capMatch) {\r\n const numericValue = parseFloat(capMatch[0]);\r\n\r\n if (capRateString.includes(\"%\") || numericValue > 1) {\r\n return Math.round((numericValue / 100) * 1000000) / 1000000;\r\n } else {\r\n return Math.round(numericValue * 1000000) / 1000000;\r\n }\r\n }\r\n\r\n return null;\r\n}\r\n\r\nexport function formatDownPaymentPercent(percentage) {\r\n return Math.round((percentage / 100) * 1000000) / 1000000;\r\n}\r\n"],"names":["mapPropertyType","type","assisted","business","mixed_use","multifamily","rv_park","str","createExportObjectCore","data","options","currentDownPaymentPercent","currentInterestRateType","currentMortgages","currentPriceDiscount","currentPropertyType","equitySource","estimatedMortgageBalance","isUsingEstimatedCapRate","noi","numberOfUnits","priceWasDefaulted","windowLocation","exportData","name","address","capRate","capMatch","match","numericValue","parseFloat","includes","Math","round","capRateSource","contact","listingDate","dateListed","price","priceMatch","replace","Number","isFinite","undefined","downPaymentPercent","equity","equityPercentFromDebt","clamped","max","min","equityPercent","Array","isArray","length","JSON","stringify","phone","priceDiscountPercent","interestRateType","propertyType","url","console","log","alphabetized","Object","keys","sort","forEach","key","calculateOriginalPrice","displayedPrice","discountPercent","convertCapRateToDecimal","capRateString","formatDownPaymentPercent","percentage"],"mappings":"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"}
|