From 655f988890f00de7364ffd1bb5d372c016b415ca Mon Sep 17 00:00:00 2001 From: Matt Hill Date: Wed, 19 Mar 2025 09:58:44 -0600 Subject: [PATCH] also do 8949 for fifo --- fifo/index.js | 79 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) diff --git a/fifo/index.js b/fifo/index.js index 0ec1964..36a9d85 100644 --- a/fifo/index.js +++ b/fifo/index.js @@ -2,6 +2,8 @@ const csvToJson = require('convert-csv-to-json') const converter = require('json-2-csv') const fs = require('fs') const BN = require('bignumber.js') +const { PDFDocument } = require('pdf-lib') +const year = 2024 const txs = csvToJson.fieldDelimiter(',').getJsonFromCsv(`../Ledger.csv`) let lots = [] @@ -111,3 +113,80 @@ converter.json2csv(dispositions).then(csv => converter.json2csv(balances).then(csv => fs.appendFileSync(`./balances.csv`, csv) ) + +// **** 8949 **** + +const getDate = (date) => { + const dateObj = new Date(date) + const month = dateObj.getMonth() + 1 + const day = dateObj.getDate() + const year = dateObj.getFullYear() + + return month + "/" + day + "/" + year; +} + +const fillFormRows = (form, page, disposition, i) => { + const dateAcquired = getDate(disposition.DateAcquired) + const dateSold = getDate(disposition.Date) + + const name = `topmostSubform[0].Page${page}[0].Table_Line1[0].Row${i + 1}[0].f${page}_` + form.getTextField(`${name}${i * 8 + 3}[0]`).setText(disposition.Asset) + form.getTextField(`${name}${i * 8 + 4}[0]`).setText(dateAcquired) + form.getTextField(`${name}${i * 8 + 5}[0]`).setText(dateSold) + form.getTextField(`${name}${i * 8 + 6}[0]`).setText(disposition.Proceeds.toString()) + form.getTextField(`${name}${i * 8 + 7}[0]`).setText(disposition.CostBasis.toString()) + form.getTextField(`${name}${i * 8 + 10}[0]`).setText(disposition.GainLoss.toString()) +} + +const fillFormTotals = (form, page, proceeds, basis) => { + form.getTextField(`topmostSubform[0].Page${page}[0].f${page}_115[0]`).setText(proceeds.toFixed(2)) + form.getTextField(`topmostSubform[0].Page${page}[0].f${page}_116[0]`).setText(basis.toFixed(2)) + form.getTextField(`topmostSubform[0].Page${page}[0].f${page}_119[0]`).setText(proceeds.minus(basis).toFixed(2)) +} + +const createPDF = async () => { + const pdfDoc = await PDFDocument.create() + + const stDispositions = dispositions.filter(d => d.ShortTerm && new Date(d.Date).getFullYear() === year) + const ltDispositions = dispositions.filter(d => !d.ShortTerm && new Date(d.Date).getFullYear() === year) + + const maxTxs = Math.max(stDispositions.length, ltDispositions.length) + const numPages = Math.ceil(maxTxs / 14) + + for (let i = 0; i < numPages; i++) { + const blank8949Bytes = fs.readFileSync('../' + year + '-f8949.pdf') + const blank8949 = await PDFDocument.load(blank8949Bytes) + const form = blank8949.getForm() + const start = i * 14 + // short term + const st = stDispositions.slice(start, start + 14) + const stTotals = st.reduce((totals, d, i) => { + fillFormRows(form, 1, d, i) + totals.proceeds = totals.proceeds.plus(d.Proceeds) + totals.basis = totals.basis.plus(d.CostBasis) + return totals + }, { proceeds: new BN(0), basis: new BN(0) }) + fillFormTotals(form, 1, stTotals.proceeds, stTotals.basis) + // long term + const lt = ltDispositions.slice(start, start + 14) + const ltTotals = lt.reduce((totals, d, i) => { + fillFormRows(form, 2, d, i) + totals.proceeds = totals.proceeds.plus(d.Proceeds) + totals.basis = totals.basis.plus(d.CostBasis) + return totals + }, { proceeds: new BN(0), basis: new BN(0) }) + fillFormTotals(form, 2, ltTotals.proceeds, ltTotals.basis) + + await blank8949.save() + + const [page1, page2] = await pdfDoc.copyPages(blank8949, [0,1]) + pdfDoc.addPage(page1) + pdfDoc.addPage(page2) + } + + const pdfBytes = await pdfDoc.save() + + fs.writeFileSync(`./8949.pdf`, pdfBytes) +} + +createPDF()