I’m having the same issue reported here: Using `tp.file.create_new` on Multiple Files in a Row with the Same Template Results in Files Getting Same Content · Issue #1080 · SilentVoid13/Templater · GitHub but applying the recomendations there I can’t make it work.
I have notes in my recurrentes folder with every expenses that have a recurring due date.
I have a template called movimientos_periodos with this code. This template ask me for which period I want to add the new notes. Then looks for all the notes in recurrentes folder, where the due date equals the selected period. Then gets all the metadata properties for this notes. Then I ask it to create a new note with the template _include_movimientos_fijos for each note meating the criteria. This is my movimientos_periodos template that I call with alt+n with Templater.
Note: There might be some unused or strange code, that I’ve been adding with all my tests, Or that I add to make clear which note has been created and is missing the template (that is why I added +"_"+recurrent.basename
after my desire filename.
<%*
/////////////////////////////////////////////////////
async function createFileIfNotExists(create_in_path, template_file, create_in) {
let file_name = tp.date.now("YYYYMMDD_hhmmssSSS")+"_"+recurrent.basename;
let file_path = `${create_in_path}/${file_name}.md`;
console.log("template_file:", template_file);
// Using async/await syntax here instead of .then to ensure we don't proceed to the next iteration until both the existence check and file creation completes
const exists = await tp.file.exists(file_path);
if (!exists) {
//console.log("Creating holidays for ", file_name);
// Awaiting so we're only creating one file at a time
await tp.file.create_new(template_file, file_name, false, create_in);
}
}
/////////////////////////////////////////////////////
let recurrente;
let recurrent = {};
//let randomID;
let estado;
let MovVencimiento;
let opcion = "todos";
// Pido el periodo
let periodo = "";
periodo = await tp.user.system_suggester_folder("Data/Periodos", "Elegir Periodo", tp, app);
// Obtener todas las notas recurrentes
const dv = app.plugins.plugins.dataview.api;
const todasLasNotasRecurrentes = dv.pagePaths('"Data/Recurrentes"');
for (let i = 0; i < todasLasNotasRecurrentes.length; ++i) {
let notaRecurrente = todasLasNotasRecurrentes[i];
// Verificar si notaRecurrente está definida
if (notaRecurrente) {
// Obtener el tfile y el frontmatter de metadataCache de la nota recurrente
let recurrente_tfile = tp.file.find_tfile(notaRecurrente);
let recurrente_cache = app.metadataCache.getFileCache(recurrente_tfile);
// Crear una variable 'recurrent' y asignar las propiedades del frontmatter
for (let prop in recurrente_cache.frontmatter) {
recurrent[prop] = recurrente_cache.frontmatter[prop];
}
// Asignar las propiedades adicionales de tfile
recurrent.path = recurrente_tfile.path;
recurrent.basename = recurrente_tfile.basename;
//console.log ("recurrent.basename", recurrent.basename);
// Calcular el vencimiento para esta nota recurrente
let MovVencimiento = await tp.user.calcular_movimiento_vencimiento(recurrent.vencimiento_recurrencia, periodo.title, recurrent.vencimiento_dia, recurrent.vencimiento_mes, recurrent.vencimiento_anio, tp, opcion);
// Verificar si el vencimiento está dentro del periodo especificado
if (MovVencimiento !== null) {
// Crear una nota de movimiento
let randomID = await tp.user.random_id(tp);
estado = "PENDIENTE";
let title = randomID;
filename = randomID+"__"+recurrent.basename;
/////////////////////////////////////////////////////
// Llamo a la función para generar cada archivo
let create_in_path = "_inbox/testing_recurrent/";
let create_in = app.vault.getAbstractFileByPath(create_in_path);
let template_file = tp.file.find_tfile("_include_movimientos_fijos");
await createFileIfNotExists(create_in_path, template_file, create_in);
/////////////////////////////////////////////////////
}
} else {
console.log("La nota recurrente es undefined. Revisar el código para asegurar que notaRecurrente se esté asignando correctamente.");
}
}
-%>
the template _include_movimientos_fijos
only has "asdfasdfasdf"
as text for now. (problem aside… that I have not search a solution yet, is that if I try to pass information to that template like asdfasdfasdfasdf - <%* tR += randomID %>
I get Templater Error: Template parsing error, aborting. randomID is not defined). I know that in the middle of hundreds of tests I’ve made, this was working fine, but now its not.
The problem I have is that when I execute the template the new notes are created, but the template is not always assigned to all notes. I have 3 notes in recurrentes folder, and in the new ones created at testing_recurrent the template is not applied to all notes. Sometimes two of them get it, other times only one.
If I change the function await tp.file.create_new(template_file, file_name, false, create_in);
for tp.file.create_new("any text here", file_name, false, create_in);
it’s still not applying the text “any text here” to all the notes created.
I tried using await tp.file.move("_inbox/testing_recurrent/" + filename);
it recursively assigns the template to the same file. I end up having only one file that was converted and renamed three times.
I have been changing my templates to be called from Quickadd, so I have them all organized there. How can I make a command in quickadd that executes all that logic and creates one one for each recurring expense applying the template _include_movimientos_fijos ?
The period could be a quickadd capture, giving as options the notes I have in my periods folder, those notes are names 2024-02, 2024-04. It should have the option to add a new one If the one I need is not created. (I have a templater template for periods) that I can call.
The original _include_movimientos_fijos should include this
---
-- METADATA:
title: <%* tR += randomID %>
filename: <%* tR += randomID %>
tags: <%* /*tR += tags*/ %>
id: <%* tR += randomID %>
adjunto-temporal:
source:
revisado: true
___metadata1:
___metadata2:
-- BASICO:
Fecha: <%* tR += MovVencimiento %>
DataTipo: "[[Movimientos]]"
___Basico1:
___Basico2:
-- MOVIMIENTO:
MovTipo: <%* tR += recurrent.MovTipo %>
CostoTipo: <%* tR += recurrent.CostoTipo %>
recurrente: <%* tR += "[["+ recurrent.path + "|" + recurrent.basename + "]]" %>
vencimiento_recurrencia: <%* tR += recurrent.vencimiento_recurrencia %>
MovListaProvisorio: Vencimientos
MovDetalle: <%* tR += recurrent.MovDetalle %>
MovEstado: <%* tR += estado %>
MovPeriodo: <%* tR += periodo.title %>
MovVencimiento: <%* tR += MovVencimiento %>
MovDestino: "<%* tR += recurrent.MovDestino %>"
movCategoria: "<%* tR += recurrent.movCategoria %>"
-- FISCAL:
ComprobanteGuardar: <%* tR += recurrent.ComprobanteGuardar %>
ComprasCargar: <%* tR += recurrent.ComprasCargar %>
ComprasPeriodo:
-- IMPORTES:
ImporteARS: <%* tR += recurrent.ImporteARS %>
ImporteUSD: <%* tR += recurrent.ImporteUSD %>
TipoAsiento: <%* tR += recurrent.TipoAsiento %>
Cotizacion:
FaltanDatos:
___Importes1:
___Importes2:
___-- LIBROS DIARIO Y MAYOR:
___Libros1:
___Libros2:
-- ASIENTOS AUTOMÁTICOS:
.. ARS:
EgresoARS(D): 0
IngresoARS(H): 0
.. USD:
EgresoUSD(D): 0
IngresoUSD(H): 0
.. TOTAL:
EgresoTotal(D): 0
IngresoTotal(H): 0
SaldoTotal:
___.. ASIENTOS EXTRA:
___Asientos1:
___Asientos2:
---
## Relaciones
Movimiento__DocumentosContables::
Movimiento__Cuotas::
## Detalle:
## DocumentosContables:
//DataviewDocumentosContables//
## Extras:
**
??
++
$$
Ignore the strange properties names and symbols, I hide them with CSS for now. They are placeholders to be replaced for actual properties if I need them. I’m still working in my expense workflow, so I use it to add things that I’m realizing now that I may need.
The system uses my calcular_movimiento_vencimiento.js that has this to check if each note should be considered to be added to the period:
async function calcular_movimiento_vencimiento(vencimiento_recurrencia, periodo, vencimiento_dia, vencimiento_mes, vencimiento_anio, tp, opcion) {
const [periodo_anio, periodo_mes] = periodo.split("-").map(Number);
let vencimiento_dia_num = parseInt(vencimiento_dia);
let vencimiento_mes_num = parseInt(vencimiento_mes);
let vencimiento_anio_num = parseInt(vencimiento_anio);
switch (vencimiento_recurrencia) {
case "mensual":
return periodo_anio + "-" + periodo_mes.toString().padStart(2, '0') + "-" + vencimiento_dia_num.toString().padStart(2, '0');
case "anual":
// Si el mes del periodo y de la recurrencia coinciden, directamente pongo esa información.
if (periodo_mes === vencimiento_mes_num) {
return periodo_anio + "-" + vencimiento_mes_num.toString().padStart(2, '0') + "-" + vencimiento_dia_num.toString().padStart(2, '0');
// Si el mes del periodo es diferente del mes de la recurrencia con un suggester pregunto si cancelo o lo agrego con nuevo vencimiento.
}else {
if (opcion === "solo_uno") {
const respuesta = await tp.system.suggester(["Sí", "No"], ["Sí", "No"], true, `Vencimiento anual mes ${vencimiento_mes} no coincide con periodo ${periodo} ¿Desea agregarlo igual?`);
if (respuesta === "No") {
return null;
} else {
// Solicitar un nuevo MovVencimiento
MovVencimiento = await tp.user.date_picker(tp);
return MovVencimiento;
}
} else {
return null;
}
}
case "decenal":
// Calcular el año de inicio y fin de la década
const vencimiento_10_anios = vencimiento_anio_num + 10;
// Verificar si el año del periodo coincide con el vencimiento_anio o con vencimiento_anio + 10 o con vencimiento_anio + 20, etc.
const esDecenal = (periodo_anio >= vencimiento_anio_num && (periodo_anio - vencimiento_anio_num) % 10 === 0) ||
(periodo_anio >= vencimiento_10_anios && (periodo_anio - vencimiento_10_anios) % 10 === 0);
if (periodo_mes === vencimiento_mes_num && esDecenal) {
return periodo_anio + "-" + vencimiento_mes_num.toString().padStart(2, '0') + "-" + vencimiento_dia_num.toString().padStart(2, '0');
} else {
if (opcion === "solo_uno") {
const respuesta = await tp.system.suggester(["Sí", "No"], ["Sí", "No"], true, `Vencimiento decenal ${vencimiento_anio}-${vencimiento_mes} no coincide con periodo ${periodo} ¿Desea agregarlo igual?`);
if (respuesta === "No") {
return null;
} else {
// Solicitar un nuevo MovVencimiento
MovVencimiento = await tp.user.date_picker(tp);
return MovVencimiento;
}
} else {
return null;
}
}
case "personalizado":
// Convertir el día y el mes en números enteros
const lista_meses = vencimiento_mes.split(",").map(mes => parseInt(mes.trim()));
// Generar las fechas personalizadas para cada mes
const lista_fechas = lista_meses.map(mes => {
return periodo_anio + "-" + mes + "-" + vencimiento_dia_num;
});
// Verificar si el mes del periodo coincide con alguno de los meses personalizados
if (lista_meses.includes(periodo_mes)) {
return periodo_anio + "-" + periodo_mes.toString().padStart(2, '0') + "-" + vencimiento_dia_num.toString().padStart(2, '0');
} else {
if (opcion === "solo_uno") {
const respuesta = await tp.system.suggester(["Sí", "No"], ["Sí", "No"], true, `Vencimiento los meses ${lista_meses} y no coincide con el periodo ${periodo}. ¿Desea agregarlo igual?`);
if (respuesta === "No") {
return null;
} else {
// Solicitar un nuevo MovVencimiento
MovVencimiento = await tp.user.date_picker(tp);
return MovVencimiento;
}
} else {
return null;
}
}
default:
console.warn(`Recurrencia no reconocida. Revisar Base de datos de Vencimientos Recurrentes, que no haya un vencimiento recurrente con un vencimiento_recurrente erróneo.`);
return null;
}
}
module.exports = calcular_movimiento_vencimiento;
It also uses a user function system_suggester_folder.js with this code, that creates a suggester with notes of a folder
async function system_suggester_folder(path, suggesterHelp, tp, app) {
// Busco los archivos en la ruta especificada
const alternatives = [];
const files = await app.vault.getMarkdownFiles().filter(x => x.parent?.path === path);
// Busco el title para las alternativas encontradas anteriormente
files.map(file => {
const fileCache = app.metadataCache.getFileCache(file);
// Si el archivo no tiene especificado un title en el frontmatter, muestro el basename
if (fileCache?.frontmatter?.title) {
file.title = fileCache?.frontmatter?.title;
}else{
file.title = file.basename;
}
// Envío en las alternativas el path, basename y title que luego puedo usar en mi template
alternatives.push({ path: file.path, basename: file.basename, title: file.title });
});
// Armo el systemSuggester con las opciones obtenidas
const selectedData = await tp.system.suggester(item => item.basename + (item?.title != item.basename ? `\n↳ ${ item?.title }` : ""), alternatives, true, suggesterHelp, 10);
return selectedData;
}
module.exports = system_suggester_folder;
the movVencimiento that I apply to Fecha, is a date with the format 2024-04-18. I want to create the randomID adapting this movVencimiento to YYYYMMDD_HHmmssSSS, having the part HHmmssSSS to be the one from the moment this is being created.
something like
const formattedDate = fecha.replace(/-/g, ''); // Eliminar los guiones
id = formattedDate + tp.date.now("HHmmssSSS");
This would be the filename and the randomID that later I retrieve to apply to some child related notes.
Can you help me with the logic with Quickadd? I think I prefer this than the method only with templater, cause there it creates first an untitled note, that is still there after creating the other notes.
I hope I explained myself. (sorry for the typing mistakes, too much text and english is not my native language)