diff --git a/models/types.ts b/models/types.ts index 800348fc..e68fea77 100644 --- a/models/types.ts +++ b/models/types.ts @@ -6,7 +6,6 @@ export enum ModelNameEnum { Address = 'Address', Batch= 'Batch', Color = 'Color', - CompanySettings = 'CompanySettings', Currency = 'Currency', GetStarted = 'GetStarted', Defaults = 'Defaults', diff --git a/schemas/app/CompanySettings.json b/schemas/app/CompanySettings.json deleted file mode 100644 index 61f5e62b..00000000 --- a/schemas/app/CompanySettings.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "name": "CompanySettings", - "label": "Company Settings", - "naming": "autoincrement", - "isSingle": true, - "isChild": false, - "fields": [ - { - "fieldname": "companyName", - "label": "Company Name", - "fieldtype": "Data", - "required": true - }, - { - "fieldname": "companyAddress", - "label": "Company Address", - "fieldtype": "Link", - "required": true, - "target": "Address" - } - ] -} diff --git a/schemas/schemas.ts b/schemas/schemas.ts index e560ab85..811049e9 100644 --- a/schemas/schemas.ts +++ b/schemas/schemas.ts @@ -4,7 +4,6 @@ import AccountingSettings from './app/AccountingSettings.json'; import Address from './app/Address.json'; import Batch from './app/Batch.json'; import Color from './app/Color.json'; -import CompanySettings from './app/CompanySettings.json'; import Currency from './app/Currency.json'; import Defaults from './app/Defaults.json'; import GetStarted from './app/GetStarted.json'; @@ -75,7 +74,6 @@ export const appSchemas: Schema[] | SchemaStub[] = [ NumberSeries as Schema, PrintSettings as Schema, - CompanySettings as Schema, Account as Schema, AccountingSettings as Schema, diff --git a/src/pages/TemplateBuilder.vue b/src/pages/TemplateBuilder.vue index ec64b3c3..bb3bd22a 100644 --- a/src/pages/TemplateBuilder.vue +++ b/src/pages/TemplateBuilder.vue @@ -4,7 +4,15 @@
-
+
+ +
+
{{ t`Select a Template Type` }}
+
+ {{ t`Select a Display Doc to view the Template` }} +
+
+
@@ -116,6 +124,10 @@ import { ModelNameEnum } from 'models/types'; import { Field, TargetField } from 'schemas/types'; import FormControl from 'src/components/Controls/FormControl.vue'; import PageHeader from 'src/components/PageHeader.vue'; +import { + getPrintTemplatePropHints, + getPrintTemplatePropValues, +} from 'src/utils/printTemplates'; import { getDocFromNameIfExistsElseNew } from 'src/utils/ui'; import { getMapFromList } from 'utils/index'; import { computed, defineComponent } from 'vue'; @@ -147,6 +159,11 @@ export default defineComponent({ if (!this.doc?.template) { this.helpersCollapsed = false; } + + // @ts-ignore + window.hints = getPrintTemplatePropHints; + // @ts-ignore + window.values = getPrintTemplatePropValues; }, methods: { async setDoc() { diff --git a/src/utils/printTemplates.ts b/src/utils/printTemplates.ts new file mode 100644 index 00000000..1d5f9a89 --- /dev/null +++ b/src/utils/printTemplates.ts @@ -0,0 +1,205 @@ +import { Fyo } from 'fyo'; +import { Doc } from 'fyo/model/doc'; +import { Invoice } from 'models/baseModels/Invoice/Invoice'; +import { ModelNameEnum } from 'models/types'; +import { FieldTypeEnum, Schema, TargetField } from 'schemas/types'; + +type PrintTemplateData = Record; + +const printSettingsFields = [ + 'logo', + 'displayLogo', + 'displayTaxInvoice', + 'color', + 'font', + 'email', + 'phone', + 'address', +]; +const accountingSettingsFields = ['companyName', 'gstin']; + +export async function getPrintTemplatePropValues(doc: Doc) { + const fyo = doc.fyo; + const values: PrintTemplateData = {}; + values.doc = await getPrintTemplateDocValues(doc); + + const printSettings = await fyo.doc.getDoc(ModelNameEnum.PrintSettings); + const printValues = await getPrintTemplateDocValues( + printSettings, + printSettingsFields + ); + + const accountingSettings = await fyo.doc.getDoc( + ModelNameEnum.AccountingSettings + ); + const accountingValues = await getPrintTemplateDocValues( + accountingSettings, + accountingSettingsFields + ); + + values.print = { + ...printValues, + ...accountingValues, + }; + + if (doc.schemaName?.endsWith('Invoice')) { + (values.doc as PrintTemplateData).totalDiscount = + formattedTotalDiscount(doc); + (values.doc as PrintTemplateData).showHSN = showHSN(doc); + } + + return values; +} + +export function getPrintTemplatePropHints(doc: Doc) { + const hints: PrintTemplateData = {}; + const fyo = doc.fyo; + hints.doc = getPrintTemplateDocHints(doc.schema, doc.fyo); + + const printSettingsHints = getPrintTemplateDocHints( + fyo.schemaMap[ModelNameEnum.PrintSettings]!, + doc.fyo, + printSettingsFields + ); + const accountingSettingsHints = getPrintTemplateDocHints( + fyo.schemaMap[ModelNameEnum.AccountingSettings]!, + doc.fyo, + accountingSettingsFields + ); + + hints.print = { + ...printSettingsHints, + ...accountingSettingsHints, + }; + + if (doc.schemaName?.endsWith('Invoice')) { + (hints.doc as PrintTemplateData).totalDiscount = fyo.t`Total Discount`; + (hints.doc as PrintTemplateData).showHSN = fyo.t`Show HSN`; + } + + return hints; +} + +function showHSN(doc: Doc): boolean { + if (!Array.isArray(doc.items)) { + return false; + } + + return doc.items.map((i) => i.hsnCode).every(Boolean); +} + +function formattedTotalDiscount(doc: Doc): string { + if (!(doc instanceof Invoice)) { + return ''; + } + + const totalDiscount = doc.getTotalDiscount(); + if (!totalDiscount?.float) { + return ''; + } + + return doc.fyo.format(totalDiscount, ModelNameEnum.Currency); +} + +function getPrintTemplateDocHints( + schema: Schema, + fyo: Fyo, + fieldnames?: string[], + isLink?: boolean +): PrintTemplateData { + isLink ??= false; + const hints: PrintTemplateData = {}; + const links: PrintTemplateData = {}; + + let fields = schema.fields; + if (fieldnames) { + fields = fields.filter((f) => fieldnames.includes(f.fieldname)); + } + + for (const field of fields) { + const { fieldname, fieldtype, label, meta } = field; + if (fieldtype === FieldTypeEnum.Attachment || meta) { + continue; + } + + hints[fieldname] = label ?? fieldname; + if (fieldtype === FieldTypeEnum.Table) { + } + + const { target } = field as TargetField; + const targetSchema = fyo.schemaMap[target]; + if (fieldtype === FieldTypeEnum.Link && targetSchema && !isLink) { + links[fieldname] = getPrintTemplateDocHints( + targetSchema, + fyo, + undefined, + true + ); + } + + if (fieldtype === FieldTypeEnum.Table && targetSchema) { + hints[fieldname] = [getPrintTemplateDocHints(targetSchema, fyo)]; + } + } + + if (Object.keys(links).length) { + hints.links = links; + } + return hints; +} + +async function getPrintTemplateDocValues(doc: Doc, fieldnames?: string[]) { + const values: PrintTemplateData = {}; + if (!(doc instanceof Doc)) { + return values; + } + + let fields = doc.schema.fields; + if (fieldnames) { + fields = fields.filter((f) => fieldnames.includes(f.fieldname)); + } + + // Set Formatted Doc Data + for (const field of fields) { + const { fieldname, fieldtype, meta } = field; + if (fieldtype === FieldTypeEnum.Attachment || meta) { + continue; + } + + const value = doc.get(fieldname); + + if (!value) { + values[fieldname] = ''; + continue; + } + + if (!Array.isArray(value)) { + values[fieldname] = doc.fyo.format(value, field, doc); + continue; + } + + const table: PrintTemplateData[] = []; + for (const row of value) { + const rowProps = await getPrintTemplateDocValues(row); + table.push(rowProps); + } + + values[fieldname] = table; + } + + // Set Formatted Doc Link Data + await doc.loadLinks(); + const links: PrintTemplateData = {}; + for (const [linkName, linkDoc] of Object.entries(doc.links ?? {})) { + if (fieldnames && !fieldnames.includes(linkName)) { + continue; + } + + links[linkName] = await getPrintTemplateDocValues(linkDoc); + } + + if (Object.keys(links).length) { + values.links = links; + } + return values; +}