diff --git a/Dockerfile b/Dockerfile index 3fefd3c8..7ceb26dd 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,47 +1,6 @@ -FROM node:21-alpine as base - -WORKDIR /usr/app -COPY ./package.json \ - ./package-lock.json \ - ./next.config.js \ - ./tsconfig.json \ - ./reset.d.ts \ - ./tailwind.config.js \ - ./postcss.config.js ./ -COPY ./scripts ./scripts -COPY ./prisma ./prisma -COPY ./src ./src - -RUN apk add --no-cache openssl && \ - npm ci --ignore-scripts && \ - npx prisma generate - -ENV NEXT_TELEMETRY_DISABLED=1 - -COPY scripts/build.env .env +FROM node:18.17 +WORKDIR '/app' +COPY . . +RUN npm install RUN npm run build - -RUN rm -r .next/cache - -FROM node:21-alpine as runtime-deps - -WORKDIR /usr/app -COPY --from=base /usr/app/package.json /usr/app/package-lock.json ./ -COPY --from=base /usr/app/prisma ./prisma - -RUN npm ci --omit=dev --omit=optional --ignore-scripts && \ - npx prisma generate - -FROM node:21-alpine as runner - -EXPOSE 3000/tcp -WORKDIR /usr/app - -COPY --from=base /usr/app/package.json /usr/app/package-lock.json ./ -COPY --from=runtime-deps /usr/app/node_modules ./node_modules -COPY ./public ./public -COPY ./scripts ./scripts -COPY --from=base /usr/app/prisma ./prisma -COPY --from=base /usr/app/.next ./.next - -ENTRYPOINT ["/bin/sh", "/usr/app/scripts/container-entrypoint.sh"] +CMD ["npm", "run", "start"] diff --git a/generateSQLImport.mjs b/generateSQLImport.mjs new file mode 100644 index 00000000..e84139da --- /dev/null +++ b/generateSQLImport.mjs @@ -0,0 +1,62 @@ +import { nanoid } from 'nanoid'; +import csv from 'csv-parser'; +import fs from 'fs'; +const results = []; + +const csv_file = 'ankit-b-and-ankita_2024-01-10_export.csv' +fs.createReadStream(csv_file) + .pipe(csv()) + .on('data', (data) => results.push(data)) + .on('end', () => { + generate(results); + // [ + // { NAME: 'Daffy Duck', AGE: '24' }, + // { NAME: 'Bugs Bunny', AGE: '22' } + // ] + }); +function generate(results) { + const out = []; + const ankitId = '_UDudHPzVb2dAzgL_-JzC'; + const ankitaId = 'xvRgcH6r4ep7YzF09KSA6'; + const groupId = 'mV9UrER7TP3yTQJa1tNAA'; + results.forEach(expense => { + const expenses = []; + if (expense.Currency !== 'USD') { + return; + } + + if (expense['Ankit Bahl'] === '0.00' && expense['Ankita'] === '0.00') { + return; + } + const paidBy = expense['Ankit Bahl'] > 0 ? ankitId : ankitaId; + const isReimbursement = expense.Category === 'Payment' ? "TRUE" : "FALSE"; + let splitMode = 'EVENLY'; + const cost = parseInt(expense.Cost.replace('.','')); + const expenseId = nanoid(); + if (Math.round(cost / 2) === Math.abs(parseInt(expense['Ankit Bahl'].replace('.','')))) { + expenses.push(`INSERT INTO "ExpensePaidFor"("expenseId", "participantId", "shares") VALUES ('${expenseId}', '${ankitId}', 100)`) + expenses.push(`INSERT INTO "ExpensePaidFor"("expenseId", "participantId", "shares") VALUES ('${expenseId}', '${ankitaId}', 100)`) + } else { + if (isReimbursement === 'TRUE') { + const participant = expense['Ankit Bahl'] > 0 ? ankitaId : ankitId; + expenses.push(`INSERT INTO "ExpensePaidFor"("expenseId", "participantId", "shares") VALUES ('${expenseId}', '${participant}', 1)`) + } else { + splitMode = 'BY_AMOUNT'; + // subtract cost from abs of expense + who is paying vs participant + if (paidBy === ankitId) { + const ankitOwed = parseInt(expense['Ankit Bahl'].replace('.','')); + expenses.push(`INSERT INTO "ExpensePaidFor"("expenseId", "participantId", "shares") VALUES ('${expenseId}', '${ankitId}', ${cost - ankitOwed})`); + expenses.push(`INSERT INTO "ExpensePaidFor"("expenseId", "participantId", "shares") VALUES ('${expenseId}', '${ankitaId}', ${ankitOwed})`); + } else { + const ankitaOwed = parseInt(expense['Ankita'].replace('.','')); + expenses.push(`INSERT INTO "ExpensePaidFor"("expenseId", "participantId", "shares") VALUES ('${expenseId}', '${ankitId}', ${ankitaOwed})`); + expenses.push(`INSERT INTO "ExpensePaidFor"("expenseId", "participantId", "shares") VALUES ('${expenseId}', '${ankitaId}', ${cost - ankitaOwed})`); + } + } + } + out.push(`INSERT INTO "Expense"(id, title, amount, "paidById", "groupId", "isReimbursement", "splitMode", "expenseDate") VALUES + ('${expenseId}','${expense.Description.replace(/'/g,"''")}',${cost},'${paidBy}','${groupId}','${isReimbursement}','${splitMode}','${expense.Date}')`.replace(/\n/g, '')); + out.push(...expenses); + }); + console.log(out.join(";\n")); +} diff --git a/package-lock.json b/package-lock.json index 52b0e543..903fb761 100644 --- a/package-lock.json +++ b/package-lock.json @@ -31,6 +31,7 @@ "content-disposition": "^0.5.4", "dayjs": "^1.11.10", "embla-carousel-react": "^8.0.0-rc21", + "csv-parser": "^3.0.0", "lucide-react": "^0.290.0", "nanoid": "^5.0.4", "next": "^14.1.0", @@ -4372,6 +4373,20 @@ "devOptional": true, "license": "MIT" }, + "node_modules/csv-parser": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/csv-parser/-/csv-parser-3.0.0.tgz", + "integrity": "sha512-s6OYSXAK3IdKqYO33y09jhypG/bSDHPuyCme/IdEHfWpLf/jKcpitVFyOC6UemgGk8v7Q5u2XE0vvwmanxhGlQ==", + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "csv-parser": "bin/csv-parser" + }, + "engines": { + "node": ">= 10" + } + }, "node_modules/damerau-levenshtein": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", @@ -6516,7 +6531,6 @@ "version": "1.2.8", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", - "dev": true, "funding": { "url": "https://github.com/sponsors/ljharb" } diff --git a/package.json b/package.json index 5706b1ef..a9011a5f 100644 --- a/package.json +++ b/package.json @@ -36,6 +36,7 @@ "content-disposition": "^0.5.4", "dayjs": "^1.11.10", "embla-carousel-react": "^8.0.0-rc21", + "csv-parser": "^3.0.0", "lucide-react": "^0.290.0", "nanoid": "^5.0.4", "next": "^14.1.0",