mirror of
https://github.com/frappe/books.git
synced 2024-11-10 07:40:55 +00:00
feat: code to generate templates
This commit is contained in:
parent
91e8fa52f4
commit
23e504a67d
@ -1,3 +1,6 @@
|
||||
import { Field, FieldType } from '@/types/model';
|
||||
import frappe from 'frappe';
|
||||
|
||||
export const importable = [
|
||||
'SalesInvoice',
|
||||
'PurchaseInvoice',
|
||||
@ -7,3 +10,88 @@ export const importable = [
|
||||
'Supplier',
|
||||
'Item',
|
||||
];
|
||||
|
||||
interface TemplateField {
|
||||
label: string;
|
||||
fieldname: string;
|
||||
required: boolean;
|
||||
}
|
||||
|
||||
type LabelFieldMap = {
|
||||
[key: string]: string;
|
||||
};
|
||||
|
||||
export function getTemplateFields(doctype: string): TemplateField[] {
|
||||
const fields: TemplateField[] = [];
|
||||
|
||||
// @ts-ignore
|
||||
const primaryFields: Field[] = frappe.models[doctype].fields;
|
||||
const tableTypes: string[] = [];
|
||||
|
||||
primaryFields.forEach(
|
||||
({ label, fieldtype, childtype, fieldname, required }) => {
|
||||
if (fieldtype === FieldType.Table && childtype) {
|
||||
tableTypes.push(childtype);
|
||||
}
|
||||
|
||||
fields.push({
|
||||
label,
|
||||
fieldname,
|
||||
required: Boolean(required ?? false),
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
tableTypes.forEach((childtype) => {
|
||||
// @ts-ignore
|
||||
const childFields: Field[] = frappe.models[childtype].fields;
|
||||
childFields.forEach(({ label, fieldtype, fieldname, required }) => {
|
||||
if (fieldtype === FieldType.Table) {
|
||||
return;
|
||||
}
|
||||
|
||||
fields.push({ label, fieldname, required: Boolean(required ?? false) });
|
||||
});
|
||||
});
|
||||
|
||||
return fields;
|
||||
}
|
||||
|
||||
function getLabelFieldMap(templateFields: TemplateField[]): LabelFieldMap {
|
||||
const map: LabelFieldMap = {};
|
||||
|
||||
templateFields.reduce((acc, tf) => {
|
||||
const key = tf.label as string;
|
||||
acc[key] = tf.fieldname;
|
||||
return acc;
|
||||
}, map);
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
function getTemplate(templateFields: TemplateField[]): string {
|
||||
const labels = templateFields.map(({ label }) => `"${label}"`).join(',');
|
||||
return [labels, ''].join('\n');
|
||||
}
|
||||
|
||||
export class Importer {
|
||||
doctype: string;
|
||||
templateFields: TemplateField[];
|
||||
_map: LabelFieldMap;
|
||||
_template: string;
|
||||
|
||||
constructor(doctype: string) {
|
||||
this.doctype = doctype;
|
||||
this.templateFields = getTemplateFields(doctype);
|
||||
this._map = getLabelFieldMap(this.templateFields);
|
||||
this._template = getTemplate(this.templateFields);
|
||||
}
|
||||
|
||||
get map() {
|
||||
return this._map;
|
||||
}
|
||||
|
||||
get template() {
|
||||
return this._template;
|
||||
}
|
||||
}
|
||||
|
@ -37,11 +37,7 @@
|
||||
input-class="bg-gray-100 text-gray-900 text-base"
|
||||
class="w-1/4"
|
||||
:value="importType"
|
||||
@change="
|
||||
(v) => {
|
||||
importType = v;
|
||||
}
|
||||
"
|
||||
@change="setImportType"
|
||||
/>
|
||||
<p
|
||||
class="text-base text-base"
|
||||
@ -55,8 +51,13 @@
|
||||
<div v-if="importType">
|
||||
<hr class="mb-6" />
|
||||
<div class="flex flex-row justify-between text-base">
|
||||
<Button class="w-1/4" :padding="false">{{ secondaryLabel }}</Button>
|
||||
<Button class="w-1/4" type="primary" @click="getFile">{{
|
||||
<Button
|
||||
class="w-1/4"
|
||||
:padding="false"
|
||||
@click="handleSecondaryClick"
|
||||
>{{ secondaryLabel }}</Button
|
||||
>
|
||||
<Button class="w-1/4" type="primary" @click="handlePrimaryClick">{{
|
||||
primaryLabel
|
||||
}}</Button>
|
||||
</div>
|
||||
@ -68,17 +69,18 @@
|
||||
<script>
|
||||
import FormControl from '@/components/Controls/FormControl';
|
||||
import PageHeader from '@/components/PageHeader.vue';
|
||||
import { importable } from '@/dataImport';
|
||||
import { importable, Importer } from '@/dataImport';
|
||||
import frappe from 'frappe';
|
||||
import Button from '@/components/Button.vue';
|
||||
import { ipcRenderer } from 'electron';
|
||||
import { IPC_ACTIONS } from '@/messages';
|
||||
import { showToast } from '@/utils';
|
||||
import { getSavePath, saveData, showToast } from '@/utils';
|
||||
export default {
|
||||
components: { PageHeader, FormControl, Button },
|
||||
data() {
|
||||
return {
|
||||
file: null,
|
||||
importer: null,
|
||||
importType: '',
|
||||
};
|
||||
},
|
||||
@ -130,13 +132,42 @@ export default {
|
||||
methods: {
|
||||
cancel() {
|
||||
this.file = null;
|
||||
this.importer = null;
|
||||
this.importType = '';
|
||||
},
|
||||
handlePrimaryClick() {},
|
||||
handleSecondaryClick() {},
|
||||
saveTemplate() {},
|
||||
getImportData() {},
|
||||
async getFile() {
|
||||
handlePrimaryClick() {
|
||||
if (!this.file) {
|
||||
this.selectFile();
|
||||
return;
|
||||
}
|
||||
|
||||
this.importData();
|
||||
},
|
||||
handleSecondaryClick() {
|
||||
if (!this.file) {
|
||||
this.saveTemplate();
|
||||
return;
|
||||
}
|
||||
|
||||
this.toggleView();
|
||||
},
|
||||
async saveTemplate() {
|
||||
const template = this.importer.template;
|
||||
const templateName = this.importType + ' ' + this.t`Template`;
|
||||
const { cancelled, filePath } = await getSavePath(templateName, 'csv');
|
||||
|
||||
if (cancelled || filePath === '') {
|
||||
return;
|
||||
}
|
||||
await saveData(template, filePath);
|
||||
},
|
||||
importData() {},
|
||||
toggleView() {},
|
||||
setImportType(importType) {
|
||||
this.importType = importType;
|
||||
this.importer = new Importer(this.labelDoctypeMap[this.importType]);
|
||||
},
|
||||
async selectFile() {
|
||||
const options = {
|
||||
title: this.t`Select File`,
|
||||
properties: ['openFile'],
|
||||
|
26
src/types/model.ts
Normal file
26
src/types/model.ts
Normal file
@ -0,0 +1,26 @@
|
||||
export enum FieldType {
|
||||
Data = 'Data',
|
||||
Select = 'Select',
|
||||
Link = 'Link',
|
||||
Date = 'Date',
|
||||
Table = 'Table',
|
||||
AutoComplete = 'AutoComplete',
|
||||
Check = 'Check',
|
||||
AttachImage = 'AttachImage',
|
||||
DynamicLink = 'DynamicLink',
|
||||
Int = 'Int',
|
||||
Float = 'Float',
|
||||
Currency = 'Currency',
|
||||
Text = 'Text',
|
||||
Color = 'Color',
|
||||
}
|
||||
|
||||
export interface Field {
|
||||
fieldname: string;
|
||||
fieldtype: FieldType;
|
||||
label: string;
|
||||
childtype?: string;
|
||||
target?: string;
|
||||
default?: unknown;
|
||||
required?: number;
|
||||
}
|
Loading…
Reference in New Issue
Block a user