mirror of
https://github.com/frappe/books.git
synced 2025-03-31 23:41:32 +00:00
incr: insert or update .template.html files
- move .template.html files out of fixtures
This commit is contained in:
parent
dabcbcd2ce
commit
eda3bb7576
@ -5,6 +5,7 @@ extraResources:
|
|||||||
[
|
[
|
||||||
{ from: 'log_creds.txt', to: '../creds/log_creds.txt' },
|
{ from: 'log_creds.txt', to: '../creds/log_creds.txt' },
|
||||||
{ from: 'translations', to: '../translations' },
|
{ from: 'translations', to: '../translations' },
|
||||||
|
{ from: 'translations', to: '../translations' },
|
||||||
]
|
]
|
||||||
mac:
|
mac:
|
||||||
type: distribution
|
type: distribution
|
||||||
|
2
main.ts
2
main.ts
@ -4,7 +4,7 @@ import {
|
|||||||
app,
|
app,
|
||||||
BrowserWindow,
|
BrowserWindow,
|
||||||
BrowserWindowConstructorOptions,
|
BrowserWindowConstructorOptions,
|
||||||
protocol
|
protocol,
|
||||||
} from 'electron';
|
} from 'electron';
|
||||||
import Store from 'electron-store';
|
import Store from 'electron-store';
|
||||||
import { autoUpdater } from 'electron-updater';
|
import { autoUpdater } from 'electron-updater';
|
||||||
|
41
main/getPrintTemplates.ts
Normal file
41
main/getPrintTemplates.ts
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
import fs from 'fs/promises';
|
||||||
|
import path from 'path';
|
||||||
|
import { TemplateFile } from 'utils/types';
|
||||||
|
|
||||||
|
export async function getTemplates() {
|
||||||
|
const paths = await getPrintTemplatePaths();
|
||||||
|
if (!paths) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
const templates: TemplateFile[] = [];
|
||||||
|
for (const file of paths.files) {
|
||||||
|
const filePath = path.join(paths.root, file);
|
||||||
|
const template = await fs.readFile(filePath, 'utf-8');
|
||||||
|
const { mtime } = await fs.stat(filePath);
|
||||||
|
templates.push({ template, file, modified: mtime.toISOString() });
|
||||||
|
}
|
||||||
|
|
||||||
|
return templates;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getPrintTemplatePaths(): Promise<{
|
||||||
|
files: string[];
|
||||||
|
root: string;
|
||||||
|
} | null> {
|
||||||
|
let root = path.join(process.resourcesPath, `../templates`);
|
||||||
|
|
||||||
|
try {
|
||||||
|
const files = await fs.readdir(root);
|
||||||
|
return { files, root };
|
||||||
|
} catch {
|
||||||
|
root = path.join(__dirname, `../templates`);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const files = await fs.readdir(root);
|
||||||
|
return { files, root };
|
||||||
|
} catch {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
@ -10,6 +10,7 @@ import { DatabaseMethod } from '../utils/db/types';
|
|||||||
import { IPC_ACTIONS } from '../utils/messages';
|
import { IPC_ACTIONS } from '../utils/messages';
|
||||||
import { getUrlAndTokenString, sendError } from './contactMothership';
|
import { getUrlAndTokenString, sendError } from './contactMothership';
|
||||||
import { getLanguageMap } from './getLanguageMap';
|
import { getLanguageMap } from './getLanguageMap';
|
||||||
|
import { getTemplates } from './getPrintTemplates';
|
||||||
import {
|
import {
|
||||||
getConfigFilesWithModified,
|
getConfigFilesWithModified,
|
||||||
getErrorHandledReponse,
|
getErrorHandledReponse,
|
||||||
@ -117,7 +118,7 @@ export default function registerIpcMainActionListeners(main: Main) {
|
|||||||
);
|
);
|
||||||
|
|
||||||
ipcMain.handle(IPC_ACTIONS.GET_CREDS, async (event) => {
|
ipcMain.handle(IPC_ACTIONS.GET_CREDS, async (event) => {
|
||||||
return await getUrlAndTokenString();
|
return getUrlAndTokenString();
|
||||||
});
|
});
|
||||||
|
|
||||||
ipcMain.handle(IPC_ACTIONS.DELETE_FILE, async (_, filePath) => {
|
ipcMain.handle(IPC_ACTIONS.DELETE_FILE, async (_, filePath) => {
|
||||||
@ -137,6 +138,10 @@ export default function registerIpcMainActionListeners(main: Main) {
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
ipcMain.handle(IPC_ACTIONS.GET_TEMPLATES, async () => {
|
||||||
|
return getTemplates();
|
||||||
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Database Related Actions
|
* Database Related Actions
|
||||||
*/
|
*/
|
||||||
|
@ -111,6 +111,8 @@ function setOnWindow(isDevelopment: boolean) {
|
|||||||
window.fyo = fyo;
|
window.fyo = fyo;
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
window.DateTime = DateTime;
|
window.DateTime = DateTime;
|
||||||
|
// @ts-ignore
|
||||||
|
window.ipcRenderer = ipcRenderer;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getPlatformName(platform: string) {
|
function getPlatformName(platform: string) {
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import { Fyo } from 'fyo';
|
import { Fyo } from 'fyo';
|
||||||
import { ConfigFile, ConfigKeys } from 'fyo/core/types';
|
import { ConfigFile, ConfigKeys } from 'fyo/core/types';
|
||||||
import { Doc } from 'fyo/model/doc';
|
|
||||||
import { getRegionalModels, models } from 'models/index';
|
import { getRegionalModels, models } from 'models/index';
|
||||||
import { ModelNameEnum } from 'models/types';
|
import { ModelNameEnum } from 'models/types';
|
||||||
import { TargetField } from 'schemas/types';
|
import { TargetField } from 'schemas/types';
|
||||||
@ -9,6 +8,7 @@ import {
|
|||||||
getRandomString,
|
getRandomString,
|
||||||
getValueMapFromList,
|
getValueMapFromList,
|
||||||
} from 'utils/index';
|
} from 'utils/index';
|
||||||
|
import { updatePrintTemplates } from './printTemplates';
|
||||||
|
|
||||||
export async function initializeInstance(
|
export async function initializeInstance(
|
||||||
dbPath: string,
|
dbPath: string,
|
||||||
@ -34,6 +34,7 @@ export async function initializeInstance(
|
|||||||
await setInstanceId(fyo);
|
await setInstanceId(fyo);
|
||||||
await setOpenCount(fyo);
|
await setOpenCount(fyo);
|
||||||
await setCurrencySymbols(fyo);
|
await setCurrencySymbols(fyo);
|
||||||
|
await updatePrintTemplates(fyo);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function closeDbIfConnected(fyo: Fyo) {
|
async function closeDbIfConnected(fyo: Fyo) {
|
||||||
|
@ -6,7 +6,7 @@ import { t } from 'fyo';
|
|||||||
import { BaseError } from 'fyo/utils/errors';
|
import { BaseError } from 'fyo/utils/errors';
|
||||||
import { BackendResponse } from 'utils/ipc/types';
|
import { BackendResponse } from 'utils/ipc/types';
|
||||||
import { IPC_ACTIONS, IPC_MESSAGES } from 'utils/messages';
|
import { IPC_ACTIONS, IPC_MESSAGES } from 'utils/messages';
|
||||||
import { SelectFileOptions, SelectFileReturn } from 'utils/types';
|
import { SelectFileOptions, SelectFileReturn, TemplateFile } from 'utils/types';
|
||||||
import { setLanguageMap } from './language';
|
import { setLanguageMap } from './language';
|
||||||
import { showMessageDialog, showToast } from './ui';
|
import { showMessageDialog, showToast } from './ui';
|
||||||
|
|
||||||
@ -14,6 +14,10 @@ export function reloadWindow() {
|
|||||||
return ipcRenderer.send(IPC_MESSAGES.RELOAD_MAIN_WINDOW);
|
return ipcRenderer.send(IPC_MESSAGES.RELOAD_MAIN_WINDOW);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function getTemplates(): Promise<TemplateFile[]> {
|
||||||
|
return await ipcRenderer.invoke(IPC_ACTIONS.GET_TEMPLATES);
|
||||||
|
}
|
||||||
|
|
||||||
export async function selectFile(
|
export async function selectFile(
|
||||||
options: SelectFileOptions
|
options: SelectFileOptions
|
||||||
): Promise<SelectFileReturn> {
|
): Promise<SelectFileReturn> {
|
||||||
|
@ -3,10 +3,14 @@ import { Doc } from 'fyo/model/doc';
|
|||||||
import { Invoice } from 'models/baseModels/Invoice/Invoice';
|
import { Invoice } from 'models/baseModels/Invoice/Invoice';
|
||||||
import { ModelNameEnum } from 'models/types';
|
import { ModelNameEnum } from 'models/types';
|
||||||
import { FieldTypeEnum, Schema, TargetField } from 'schemas/types';
|
import { FieldTypeEnum, Schema, TargetField } from 'schemas/types';
|
||||||
import { getSavePath, makePDF } from './ipcCalls';
|
import { getValueMapFromList } from 'utils/index';
|
||||||
|
import { TemplateFile } from 'utils/types';
|
||||||
|
import { getSavePath, getTemplates, makePDF } from './ipcCalls';
|
||||||
import { PrintValues } from './types';
|
import { PrintValues } from './types';
|
||||||
|
import { getDocFromNameIfExistsElseNew } from './ui';
|
||||||
|
|
||||||
type PrintTemplateData = Record<string, unknown>;
|
type PrintTemplateData = Record<string, unknown>;
|
||||||
|
type TemplateUpdateItem = { name: string; template: string; type: string };
|
||||||
|
|
||||||
const printSettingsFields = [
|
const printSettingsFields = [
|
||||||
'logo',
|
'logo',
|
||||||
@ -256,3 +260,92 @@ function getAllCSSAsStyleElem() {
|
|||||||
styleElem.innerHTML = cssTexts.join('\n');
|
styleElem.innerHTML = cssTexts.join('\n');
|
||||||
return styleElem;
|
return styleElem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function updatePrintTemplates(fyo: Fyo) {
|
||||||
|
const templateFiles = await getTemplates();
|
||||||
|
const existingTemplates = (await fyo.db.getAll(ModelNameEnum.PrintTemplate, {
|
||||||
|
fields: ['name', 'modified'],
|
||||||
|
filters: { isCustom: false },
|
||||||
|
})) as { name: string; modified: Date }[];
|
||||||
|
|
||||||
|
const nameModifiedMap = getValueMapFromList(
|
||||||
|
existingTemplates,
|
||||||
|
'name',
|
||||||
|
'modified'
|
||||||
|
);
|
||||||
|
|
||||||
|
const updateList: TemplateUpdateItem[] = [];
|
||||||
|
for (const templateFile of templateFiles) {
|
||||||
|
const updates = getPrintTemplateUpdateList(
|
||||||
|
templateFile,
|
||||||
|
nameModifiedMap,
|
||||||
|
fyo
|
||||||
|
);
|
||||||
|
|
||||||
|
updateList.push(...updates);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const { name, type, template } of updateList) {
|
||||||
|
const doc = await getDocFromNameIfExistsElseNew(
|
||||||
|
ModelNameEnum.PrintTemplate,
|
||||||
|
name
|
||||||
|
);
|
||||||
|
|
||||||
|
await doc.set({ name, type, template, isCustom: false });
|
||||||
|
await doc.sync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getPrintTemplateUpdateList(
|
||||||
|
{ file, template, modified: modifiedString }: TemplateFile,
|
||||||
|
nameModifiedMap: Record<string, Date>,
|
||||||
|
fyo: Fyo
|
||||||
|
): TemplateUpdateItem[] {
|
||||||
|
const templateList: TemplateUpdateItem[] = [];
|
||||||
|
const dbModified = new Date(modifiedString);
|
||||||
|
|
||||||
|
for (const { name, type } of getNameAndTypeFromTemplateFile(file, fyo)) {
|
||||||
|
const fileModified = nameModifiedMap[name];
|
||||||
|
if (fileModified && dbModified.valueOf() >= fileModified.valueOf()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
templateList.push({
|
||||||
|
name,
|
||||||
|
type,
|
||||||
|
template,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return templateList;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getNameAndTypeFromTemplateFile(
|
||||||
|
file: string,
|
||||||
|
fyo: Fyo
|
||||||
|
): { name: string; type: string }[] {
|
||||||
|
/**
|
||||||
|
* Template File Name Format:
|
||||||
|
* TemplateName[.SchemaName].template.html
|
||||||
|
*
|
||||||
|
* If the SchemaName is absent then it is assumed
|
||||||
|
* that the SchemaName is:
|
||||||
|
* - SalesInvoice
|
||||||
|
* - PurchaseInvoice
|
||||||
|
*/
|
||||||
|
|
||||||
|
const fileName = file.split('.template.html')[0];
|
||||||
|
const name = fileName.split('.')[0];
|
||||||
|
const schemaName = fileName.split('.')[1];
|
||||||
|
|
||||||
|
if (schemaName) {
|
||||||
|
const label = fyo.schemaMap[schemaName]?.label ?? schemaName;
|
||||||
|
return [{ name: `${name} - ${label}`, type: schemaName }];
|
||||||
|
}
|
||||||
|
|
||||||
|
return [ModelNameEnum.SalesInvoice, ModelNameEnum.PurchaseInvoice].map(
|
||||||
|
(schemaName) => {
|
||||||
|
const label = fyo.schemaMap[schemaName]?.label ?? schemaName;
|
||||||
|
return { name: `${name} - ${label}`, type: schemaName };
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
@ -22,6 +22,7 @@ export enum IPC_ACTIONS {
|
|||||||
SELECT_FILE = 'select-file',
|
SELECT_FILE = 'select-file',
|
||||||
GET_CREDS = 'get-creds',
|
GET_CREDS = 'get-creds',
|
||||||
GET_DB_LIST = 'get-db-list',
|
GET_DB_LIST = 'get-db-list',
|
||||||
|
GET_TEMPLATES = 'get-templates',
|
||||||
DELETE_FILE = 'delete-file',
|
DELETE_FILE = 'delete-file',
|
||||||
// Database messages
|
// Database messages
|
||||||
DB_CREATE = 'db-create',
|
DB_CREATE = 'db-create',
|
||||||
|
@ -23,14 +23,18 @@ export interface VersionParts {
|
|||||||
beta?: number;
|
beta?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type Creds = { errorLogUrl: string; telemetryUrl: string; tokenString: string };
|
export type Creds = {
|
||||||
|
errorLogUrl: string;
|
||||||
|
telemetryUrl: string;
|
||||||
|
tokenString: string;
|
||||||
|
};
|
||||||
|
|
||||||
export type UnexpectedLogObject = {
|
export type UnexpectedLogObject = {
|
||||||
name: string;
|
name: string;
|
||||||
message: string;
|
message: string;
|
||||||
stack: string;
|
stack: string;
|
||||||
more: Record<string, unknown>;
|
more: Record<string, unknown>;
|
||||||
}
|
};
|
||||||
|
|
||||||
export interface SelectFileOptions {
|
export interface SelectFileOptions {
|
||||||
title: string;
|
title: string;
|
||||||
@ -48,3 +52,5 @@ export interface SelectFileReturn {
|
|||||||
export type PropertyEnum<T extends Record<string, any>> = {
|
export type PropertyEnum<T extends Record<string, any>> = {
|
||||||
[key in keyof Required<T>]: key;
|
[key in keyof Required<T>]: key;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type TemplateFile = { file: string; template: string; modified: string };
|
||||||
|
Loading…
x
Reference in New Issue
Block a user