2
0
mirror of https://github.com/frappe/books.git synced 2024-11-15 09:54:04 +00:00
books/reports/commonExporter.ts

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

190 lines
4.4 KiB
TypeScript
Raw Normal View History

import { t } from 'fyo';
2022-05-18 07:04:33 +00:00
import { Action } from 'fyo/model/types';
import { Verb } from 'fyo/telemetry/types';
import { getSavePath, showExportInFolder } from 'src/utils/ui';
2022-05-18 07:04:33 +00:00
import { getIsNullOrUndef } from 'utils';
import { generateCSV } from 'utils/csvParser';
import { Report } from './Report';
2022-05-18 08:48:30 +00:00
import { ExportExtention, ReportCell } from './types';
interface JSONExport {
columns: { fieldname: string; label: string }[];
2022-05-18 07:04:33 +00:00
rows: Record<string, unknown>[];
filters: Record<string, string>;
timestamp: string;
reportName: string;
softwareName: string;
softwareVersion: string;
}
2022-05-18 07:04:33 +00:00
export default function getCommonExportActions(report: Report): Action[] {
const exportExtention = ['csv', 'json'] as ExportExtention[];
2022-05-18 07:04:33 +00:00
return exportExtention.map((ext) => ({
group: t`Export`,
label: ext.toUpperCase(),
type: 'primary',
action: async () => {
await exportReport(ext, report);
},
}));
}
2022-05-18 07:04:33 +00:00
async function exportReport(extention: ExportExtention, report: Report) {
const { filePath, canceled } = await getSavePath(
report.reportName,
extention
);
2022-05-18 07:04:33 +00:00
if (canceled || !filePath) {
return;
}
2022-05-18 08:48:30 +00:00
let data = '';
if (extention === 'csv') {
data = getCsvData(report);
} else if (extention === 'json') {
data = getJsonData(report);
}
if (!data.length) {
return;
2022-05-18 07:04:33 +00:00
}
await saveExportData(data, filePath);
2022-05-18 07:04:33 +00:00
report.fyo.telemetry.log(Verb.Exported, report.reportName, { extention });
}
2022-05-18 08:48:30 +00:00
function getJsonData(report: Report): string {
const exportObject: JSONExport = {
columns: [],
rows: [],
filters: {},
timestamp: '',
reportName: '',
softwareName: '',
softwareVersion: '',
};
2022-05-18 07:04:33 +00:00
const columns = report.columns;
const displayPrecision =
(report.fyo.singles.SystemSettings?.displayPrecision as number) ?? 2;
/**
* Set columns as list of fieldname, label
*/
exportObject.columns = columns.map(({ fieldname, label }) => ({
fieldname,
label,
}));
2022-05-18 07:04:33 +00:00
/**
* Set rows as fieldname: value map
*/
for (const row of report.reportData) {
if (row.isEmpty) {
continue;
}
const rowObj: Record<string, unknown> = {};
for (let c = 0; c < row.cells.length; c++) {
2022-05-18 07:04:33 +00:00
const { label } = columns[c];
const cell = getValueFromCell(row.cells[c], displayPrecision);
rowObj[label] = cell;
}
exportObject.rows.push(rowObj);
}
2022-05-18 07:04:33 +00:00
/**
* Set filter map
*/
for (const { fieldname } of report.filters) {
const value = report.get(fieldname);
if (getIsNullOrUndef(value)) {
continue;
}
2022-05-18 07:04:33 +00:00
exportObject.filters[fieldname] = String(value);
}
/**
* Metadata
*/
exportObject.timestamp = new Date().toISOString();
2022-05-18 07:04:33 +00:00
exportObject.reportName = report.reportName;
exportObject.softwareName = 'Frappe Books';
2022-05-18 07:04:33 +00:00
exportObject.softwareVersion = report.fyo.store.appVersion;
2022-05-18 08:48:30 +00:00
return JSON.stringify(exportObject);
}
2022-05-18 08:48:30 +00:00
export function getCsvData(report: Report): string {
2022-05-18 07:04:33 +00:00
const csvMatrix = convertReportToCSVMatrix(report);
2022-05-18 08:48:30 +00:00
return generateCSV(csvMatrix);
2022-05-18 07:04:33 +00:00
}
2022-05-18 07:04:33 +00:00
function convertReportToCSVMatrix(report: Report): unknown[][] {
const displayPrecision =
(report.fyo.singles.SystemSettings?.displayPrecision as number) ?? 2;
const reportData = report.reportData;
const columns = report.columns;
2022-05-18 07:04:33 +00:00
const csvdata: unknown[][] = [];
csvdata.push(columns.map((c) => c.label));
for (const row of reportData) {
if (row.isEmpty) {
csvdata.push(Array(row.cells.length).fill(''));
continue;
}
const csvrow: unknown[] = [];
for (let c = 0; c < row.cells.length; c++) {
2022-05-18 07:04:33 +00:00
const cell = getValueFromCell(row.cells[c], displayPrecision);
csvrow.push(cell);
}
csvdata.push(csvrow);
}
2022-05-18 07:04:33 +00:00
return csvdata;
}
2022-05-18 07:04:33 +00:00
function getValueFromCell(cell: ReportCell, displayPrecision: number) {
const rawValue = cell.rawValue;
if (rawValue instanceof Date) {
return rawValue.toISOString();
}
if (typeof rawValue === 'number') {
const value = rawValue.toFixed(displayPrecision);
/**
* remove insignificant zeroes
*/
if (value.endsWith('0'.repeat(displayPrecision))) {
return value.slice(0, -displayPrecision - 1);
}
return value;
}
if (getIsNullOrUndef(cell)) {
return '';
}
return rawValue;
}
export async function saveExportData(
data: string,
filePath: string,
message?: string
) {
await ipc.saveData(data, filePath);
message ??= t`Export Successful`;
showExportInFolder(message, filePath);
}