diff --git a/.gitignore b/.gitignore
index d3ba9217..1c3efc7b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -21,7 +21,9 @@ bin/
.README.md.html
# Intellij
-.idea/
+.idea/*
+!.idea/fileTemplates
+!.idea/file.template.settings.xml
*.iml
*.iws
diff --git a/templates/admin/.gitignore b/templates/admin/.gitignore
index c1064aff..d67507ac 100644
--- a/templates/admin/.gitignore
+++ b/templates/admin/.gitignore
@@ -22,7 +22,9 @@ bin/
.README.md.html
# Intellij
-.idea/
+.idea/*
+!.idea/fileTemplates
+!.idea/file.template.settings.xml
*.iml
*.iws
diff --git a/templates/admin/.idea/file.template.settings.xml b/templates/admin/.idea/file.template.settings.xml
new file mode 100644
index 00000000..20b0c9b9
--- /dev/null
+++ b/templates/admin/.idea/file.template.settings.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/templates/admin/.idea/fileTemplates/Component.tsx b/templates/admin/.idea/fileTemplates/Component.tsx
new file mode 100644
index 00000000..668b19fa
--- /dev/null
+++ b/templates/admin/.idea/fileTemplates/Component.tsx
@@ -0,0 +1,17 @@
+#set($kebabCase = $NAME.replaceAll("([A-Z])", "-$1").toLowerCase().substring(1))
+#set($camelCase = $NAME.substring(0, 1).toLowerCase() + $NAME.substring(1))
+#set($NAME_LOWERCASE = $NAME.substring(0,1).toLowerCase() + $NAME.substring(1))
+import React from 'react';
+import scss from './${kebabCase}.module.scss';
+
+type ${NAME}Props = {
+};
+
+export default function ${NAME}(
+ {}: ${NAME}Props
+) {
+ return (
+
+
+ );
+}
diff --git "a/templates/admin/.idea/fileTemplates/Component.tsx.child.0\340\274\217ext\340\274\217.module.scss" "b/templates/admin/.idea/fileTemplates/Component.tsx.child.0\340\274\217ext\340\274\217.module.scss"
new file mode 100644
index 00000000..eeb7efff
--- /dev/null
+++ "b/templates/admin/.idea/fileTemplates/Component.tsx.child.0\340\274\217ext\340\274\217.module.scss"
@@ -0,0 +1,4 @@
+#set($kebabCase = $NAME.replaceAll("([A-Z])", "-$1").toLowerCase().substring(1))
+.${kebabCase} {
+
+}
\ No newline at end of file
diff --git a/templates/admin/.idea/fileTemplates/Dao.java b/templates/admin/.idea/fileTemplates/Dao.java
new file mode 100644
index 00000000..bfcafa63
--- /dev/null
+++ b/templates/admin/.idea/fileTemplates/Dao.java
@@ -0,0 +1 @@
+#parse("Dao.java")
diff --git a/templates/admin/.idea/fileTemplates/ObservableClass.tsx b/templates/admin/.idea/fileTemplates/ObservableClass.tsx
new file mode 100644
index 00000000..6f4b8be4
--- /dev/null
+++ b/templates/admin/.idea/fileTemplates/ObservableClass.tsx
@@ -0,0 +1,18 @@
+#set($NAME_CAP = $NAME.substring(0,1).toUpperCase() + $NAME.substring(1))
+#set($Properties_CAP = $Properties.substring(0,1).toUpperCase() + $Properties.substring(1))
+import { observable, Observable, WritableObservable } from 'micro-observables';
+
+export class ${NAME_CAP} {
+ private readonly ${Properties}: WritableObservable
+ constructor() {
+ this.${Properties} = observable(false);
+ }
+
+ get${Properties_CAP}(): Observable {
+ return this.${Properties}.readOnly();
+ }
+
+ update${Properties_CAP}(${Properties}: boolean): void {
+ this.${Properties}.set(${Properties});
+ }
+}
\ No newline at end of file
diff --git a/templates/admin/.idea/fileTemplates/PlumeMVC.java b/templates/admin/.idea/fileTemplates/PlumeMVC.java
new file mode 100644
index 00000000..19107cd0
--- /dev/null
+++ b/templates/admin/.idea/fileTemplates/PlumeMVC.java
@@ -0,0 +1 @@
+#parse("WebService.java")
\ No newline at end of file
diff --git a/templates/admin/.idea/fileTemplates/PlumeMVC.java.child.0.java b/templates/admin/.idea/fileTemplates/PlumeMVC.java.child.0.java
new file mode 100644
index 00000000..ecd2fe40
--- /dev/null
+++ b/templates/admin/.idea/fileTemplates/PlumeMVC.java.child.0.java
@@ -0,0 +1 @@
+#parse("Service.java")
\ No newline at end of file
diff --git a/templates/admin/.idea/fileTemplates/PlumeMVC.java.child.1.java b/templates/admin/.idea/fileTemplates/PlumeMVC.java.child.1.java
new file mode 100644
index 00000000..bfcafa63
--- /dev/null
+++ b/templates/admin/.idea/fileTemplates/PlumeMVC.java.child.1.java
@@ -0,0 +1 @@
+#parse("Dao.java")
diff --git a/templates/admin/.idea/fileTemplates/PlumeMVC.java.child.2.java b/templates/admin/.idea/fileTemplates/PlumeMVC.java.child.2.java
new file mode 100644
index 00000000..da91fcf4
--- /dev/null
+++ b/templates/admin/.idea/fileTemplates/PlumeMVC.java.child.2.java
@@ -0,0 +1 @@
+#parse("Request.java")
diff --git a/templates/admin/.idea/fileTemplates/PlumeMVC.java.child.3.java b/templates/admin/.idea/fileTemplates/PlumeMVC.java.child.3.java
new file mode 100644
index 00000000..e772bb91
--- /dev/null
+++ b/templates/admin/.idea/fileTemplates/PlumeMVC.java.child.3.java
@@ -0,0 +1 @@
+#parse("Response.java")
diff --git a/templates/admin/.idea/fileTemplates/Service.java b/templates/admin/.idea/fileTemplates/Service.java
new file mode 100644
index 00000000..ecd2fe40
--- /dev/null
+++ b/templates/admin/.idea/fileTemplates/Service.java
@@ -0,0 +1 @@
+#parse("Service.java")
\ No newline at end of file
diff --git "a/templates/admin/.idea/fileTemplates/Story\340\274\217ext\340\274\217.stories.tsx" "b/templates/admin/.idea/fileTemplates/Story\340\274\217ext\340\274\217.stories.tsx"
new file mode 100644
index 00000000..2283a420
--- /dev/null
+++ "b/templates/admin/.idea/fileTemplates/Story\340\274\217ext\340\274\217.stories.tsx"
@@ -0,0 +1,16 @@
+import React from 'react';
+import type { Meta, StoryObj } from '@storybook/react';
+
+type Story = StoryObj;
+
+export const Default: Story = {
+ render: () => (
+ <${NAME} />
+ ),
+};
+
+const meta: Meta = {
+ component: ${NAME},
+};
+
+export default meta;
diff --git a/templates/admin/.idea/fileTemplates/WebService.java b/templates/admin/.idea/fileTemplates/WebService.java
new file mode 100644
index 00000000..19107cd0
--- /dev/null
+++ b/templates/admin/.idea/fileTemplates/WebService.java
@@ -0,0 +1 @@
+#parse("WebService.java")
\ No newline at end of file
diff --git a/templates/admin/.idea/fileTemplates/includes/Dao.java b/templates/admin/.idea/fileTemplates/includes/Dao.java
new file mode 100644
index 00000000..4d75dfde
--- /dev/null
+++ b/templates/admin/.idea/fileTemplates/includes/Dao.java
@@ -0,0 +1,30 @@
+#* ./db/dao/${Package}/${ResourceName}Dao *#
+
+#* @vtlvariable name="PACKAGE_NAME" type="java.lang.String" *#
+#* @vtlvariable name="ResourceName" type="java.lang.String" *#
+#if (${PACKAGE_NAME} != "")package ${PACKAGE_NAME};#end
+#set($DaoVariable = ${ResourceName} + "Dao")
+#set($QVariable = "Q" + ${ResourceName})
+#set($ResourceName_LowerCase = $ResourceName.substring(0,1).toLowerCase() + $ResourceName.substring(1))
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+import java.util.List;
+import com.coreoz.plume.db.querydsl.crud.CrudDaoQuerydsl;
+import com.coreoz.plume.db.querydsl.transaction.TransactionManagerQuerydsl;
+
+@Singleton
+public class ${ResourceName}Dao extends CrudDaoQuerydsl<${ResourceName}> {
+
+ @Inject
+ private ${ResourceName}Dao(TransactionManagerQuerydsl transactionManagerQuerydsl) {
+ super(transactionManagerQuerydsl, ${QVariable}.${ResourceName_LowerCase});
+ }
+
+ public List<${ResourceName}> fetch${ResourceName}s() {
+ return transactionManager.selectQuery()
+ .select(${QVariable}.${ResourceName_LowerCase})
+ .from(${QVariable}.${ResourceName_LowerCase})
+ .fetch();
+ }
+}
diff --git a/templates/admin/.idea/fileTemplates/includes/Request.java b/templates/admin/.idea/fileTemplates/includes/Request.java
new file mode 100644
index 00000000..16d390fe
--- /dev/null
+++ b/templates/admin/.idea/fileTemplates/includes/Request.java
@@ -0,0 +1,6 @@
+#* ./webservices/api/${Package}/data/${ResourceName}Response *#
+#* @vtlvariable name="PACKAGE_NAME" type="java.lang.String" *#
+#* @vtlvariable name="ResourceName" type="java.lang.String" *#
+#if (${PACKAGE_NAME} != "")package ${PACKAGE_NAME};#end
+
+public record ${ResourceName}Request() {}
diff --git a/templates/admin/.idea/fileTemplates/includes/Response.java b/templates/admin/.idea/fileTemplates/includes/Response.java
new file mode 100644
index 00000000..b66c0be8
--- /dev/null
+++ b/templates/admin/.idea/fileTemplates/includes/Response.java
@@ -0,0 +1,6 @@
+#* ./webservices/api/${Package}/data/${ResourceName}Response *#
+#* @vtlvariable name="PACKAGE_NAME" type="java.lang.String" *#
+#* @vtlvariable name="ResourceName" type="java.lang.String" *#
+#if (${PACKAGE_NAME} != "")package ${PACKAGE_NAME};#end
+
+public record ${ResourceName}Response() {}
diff --git a/templates/admin/.idea/fileTemplates/includes/Service.java b/templates/admin/.idea/fileTemplates/includes/Service.java
new file mode 100644
index 00000000..c4dfabbe
--- /dev/null
+++ b/templates/admin/.idea/fileTemplates/includes/Service.java
@@ -0,0 +1,49 @@
+#* ./services/${Package}/${ResourceName}Service *#
+
+#if (${PACKAGE_NAME} != "")package ${PACKAGE_NAME};#end
+#set($ResourceName_LowerCase = $ResourceName.substring(0,1).toLowerCase() + $ResourceName.substring(1))
+#set($Dao = ${ResourceName} + "Dao")
+#set($DaoVariable = ${ResourceName_LowerCase} + "Dao")
+#set($ResourceNameRequest = ${ResourceName} + "Request")
+#set($ResourceNameRequestVariable = $ResourceNameRequest.substring(0,1).toLowerCase() + $ResourceNameRequest.substring(1))
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+import java.util.List;
+
+@Singleton
+public class ${ResourceName}Service {
+ private final $Dao $DaoVariable;
+
+ @Inject
+ private ${ResourceName}Service($Dao $DaoVariable) {
+ this.${DaoVariable} = $DaoVariable;
+ }
+
+ public List<${ResourceName}> fetch${ResourceName}s() {
+ return ${DaoVariable}.fetch${ResourceName}s();
+ }
+
+ public ${ResourceName} fetch${ResourceName}ById(Long id) {
+ return ${DaoVariable}.findById(id);
+ }
+
+ public ${ResourceName} create${ResourceName}(
+ $ResourceNameRequest $ResourceNameRequestVariable
+ ) {
+ // TODO Map request to ${ResourceName}
+ return ${DaoVariable}.save();
+ }
+
+ public ${ResourceName} update${ResourceName}(
+ Long id,
+ $ResourceNameRequest $ResourceNameRequestVariable
+ ) {
+ // TODO Map request to ${ResourceName}
+ return ${DaoVariable}.save();
+ }
+
+ public long delete${ResourceName}ById(Long id) {
+ return ${DaoVariable}.delete(id);
+ }
+}
diff --git a/templates/admin/.idea/fileTemplates/includes/WebService.java b/templates/admin/.idea/fileTemplates/includes/WebService.java
new file mode 100644
index 00000000..97cf57d0
--- /dev/null
+++ b/templates/admin/.idea/fileTemplates/includes/WebService.java
@@ -0,0 +1,83 @@
+#* ./webservices/api/${Package}/${ResourceName}Ws *#
+#set($ResourceName_LowerCase = $ResourceName.substring(0,1).toLowerCase() + $ResourceName.substring(1))
+#set($ServiceVariable = ${ResourceName_LowerCase} + "Service")
+#set($ServiceClass = ${ResourceName} + "Service")
+#set($ResourceNameRequest = ${ResourceName} + "Request")
+#set($ResourceNameResponse = ${ResourceName} + "Response")
+#set($ResourceNamePutResponse = ${ResourceName} + "Response")
+#set($ResourceNameRequestVariable = $ResourceNameRequest.substring(0,1).toLowerCase() + $ResourceNameRequest.substring(1))
+
+#if (${PACKAGE_NAME} != "")package ${PACKAGE_NAME};#end
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+import java.util.List;
+
+@Path("/${ResourceName_LowerCase}" )
+@Tag(name = "${ResourceName}" , description = "Manage ${ResourceName_LowerCase} web-services" )
+@Consumes(MediaType.APPLICATION_JSON)
+@Produces(MediaType.APPLICATION_JSON)
+@Singleton
+// TODO Insert @RestrictTo or @PublicApi
+public class ${ResourceName}Ws {
+ private final ${ServiceClass} ${ServiceVariable};
+
+ @Inject
+ public ${ResourceName}Ws(${ServiceClass} ${ServiceVariable}) {
+ this.${ServiceVariable} = ${ServiceVariable};
+ }
+
+ @GET
+ @Operation(description = "Fetch ${ResourceName_LowerCase}s")
+ public List<$ResourceNameResponse> fetch${ResourceName}s() {
+ return ${ServiceVariable}.fetch${ResourceName}s();
+ }
+
+ @GET
+ @Path("/{id}" )
+ @Operation(description = "Fetch ${ResourceName_LowerCase} by id")
+ public $ResourceNameResponse fetch${ResourceName}(
+ @Parameter(required = true) @PathParam("id") Long id
+ ) {
+ return ${ServiceVariable}.fetch${ResourceName}ById(id);
+ }
+
+ @POST
+ @Operation(description = "Create ${ResourceName_LowerCase}")
+ public ${ResourceNameResponse} create${ResourceName}(
+ $ResourceNameRequest $ResourceNameRequestVariable
+ ) {
+ return ${ServiceVariable}.create${ResourceName}($ResourceNameRequestVariable);
+ }
+
+ @PUT
+ @Path("/{id}" )
+ @Operation(description = "Update ${ResourceName_LowerCase}")
+ public ${ResourceNamePutResponse} update${ResourceName}ById(
+ $ResourceNameRequest $ResourceNameRequestVariable,
+ @Parameter(required = true) @PathParam("id") Long id
+ ) {
+ return ${ServiceVariable}.update${ResourceName}(id, $ResourceNameRequestVariable);
+ }
+
+ @DELETE
+ @Operation(description = "Delete ${ResourceName_LowerCase} by id")
+ @Path("/{id}" )
+ public void delete${ResourceName}ById(
+ @Parameter(required = true) @PathParam("id") Long id
+ ) {
+ ${ServiceVariable}.delete${ResourceName}ById(id);
+ }
+}
\ No newline at end of file
diff --git a/templates/front/.gitignore b/templates/front/.gitignore
index c1064aff..d67507ac 100644
--- a/templates/front/.gitignore
+++ b/templates/front/.gitignore
@@ -22,7 +22,9 @@ bin/
.README.md.html
# Intellij
-.idea/
+.idea/*
+!.idea/fileTemplates
+!.idea/file.template.settings.xml
*.iml
*.iws
diff --git a/templates/front/.idea/file.template.settings.xml b/templates/front/.idea/file.template.settings.xml
new file mode 100644
index 00000000..20b0c9b9
--- /dev/null
+++ b/templates/front/.idea/file.template.settings.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/templates/front/.idea/fileTemplates/Component.tsx b/templates/front/.idea/fileTemplates/Component.tsx
new file mode 100644
index 00000000..668b19fa
--- /dev/null
+++ b/templates/front/.idea/fileTemplates/Component.tsx
@@ -0,0 +1,17 @@
+#set($kebabCase = $NAME.replaceAll("([A-Z])", "-$1").toLowerCase().substring(1))
+#set($camelCase = $NAME.substring(0, 1).toLowerCase() + $NAME.substring(1))
+#set($NAME_LOWERCASE = $NAME.substring(0,1).toLowerCase() + $NAME.substring(1))
+import React from 'react';
+import scss from './${kebabCase}.module.scss';
+
+type ${NAME}Props = {
+};
+
+export default function ${NAME}(
+ {}: ${NAME}Props
+) {
+ return (
+
+
+ );
+}
diff --git "a/templates/front/.idea/fileTemplates/Component.tsx.child.0\340\274\217ext\340\274\217.module.scss" "b/templates/front/.idea/fileTemplates/Component.tsx.child.0\340\274\217ext\340\274\217.module.scss"
new file mode 100644
index 00000000..eeb7efff
--- /dev/null
+++ "b/templates/front/.idea/fileTemplates/Component.tsx.child.0\340\274\217ext\340\274\217.module.scss"
@@ -0,0 +1,4 @@
+#set($kebabCase = $NAME.replaceAll("([A-Z])", "-$1").toLowerCase().substring(1))
+.${kebabCase} {
+
+}
\ No newline at end of file
diff --git a/templates/front/.idea/fileTemplates/Dao.java b/templates/front/.idea/fileTemplates/Dao.java
new file mode 100644
index 00000000..bfcafa63
--- /dev/null
+++ b/templates/front/.idea/fileTemplates/Dao.java
@@ -0,0 +1 @@
+#parse("Dao.java")
diff --git a/templates/front/.idea/fileTemplates/ObservableClass.tsx b/templates/front/.idea/fileTemplates/ObservableClass.tsx
new file mode 100644
index 00000000..6f4b8be4
--- /dev/null
+++ b/templates/front/.idea/fileTemplates/ObservableClass.tsx
@@ -0,0 +1,18 @@
+#set($NAME_CAP = $NAME.substring(0,1).toUpperCase() + $NAME.substring(1))
+#set($Properties_CAP = $Properties.substring(0,1).toUpperCase() + $Properties.substring(1))
+import { observable, Observable, WritableObservable } from 'micro-observables';
+
+export class ${NAME_CAP} {
+ private readonly ${Properties}: WritableObservable
+ constructor() {
+ this.${Properties} = observable(false);
+ }
+
+ get${Properties_CAP}(): Observable {
+ return this.${Properties}.readOnly();
+ }
+
+ update${Properties_CAP}(${Properties}: boolean): void {
+ this.${Properties}.set(${Properties});
+ }
+}
\ No newline at end of file
diff --git a/templates/front/.idea/fileTemplates/PlumeMVC.java b/templates/front/.idea/fileTemplates/PlumeMVC.java
new file mode 100644
index 00000000..19107cd0
--- /dev/null
+++ b/templates/front/.idea/fileTemplates/PlumeMVC.java
@@ -0,0 +1 @@
+#parse("WebService.java")
\ No newline at end of file
diff --git a/templates/front/.idea/fileTemplates/PlumeMVC.java.child.0.java b/templates/front/.idea/fileTemplates/PlumeMVC.java.child.0.java
new file mode 100644
index 00000000..ecd2fe40
--- /dev/null
+++ b/templates/front/.idea/fileTemplates/PlumeMVC.java.child.0.java
@@ -0,0 +1 @@
+#parse("Service.java")
\ No newline at end of file
diff --git a/templates/front/.idea/fileTemplates/PlumeMVC.java.child.1.java b/templates/front/.idea/fileTemplates/PlumeMVC.java.child.1.java
new file mode 100644
index 00000000..bfcafa63
--- /dev/null
+++ b/templates/front/.idea/fileTemplates/PlumeMVC.java.child.1.java
@@ -0,0 +1 @@
+#parse("Dao.java")
diff --git a/templates/front/.idea/fileTemplates/PlumeMVC.java.child.2.java b/templates/front/.idea/fileTemplates/PlumeMVC.java.child.2.java
new file mode 100644
index 00000000..da91fcf4
--- /dev/null
+++ b/templates/front/.idea/fileTemplates/PlumeMVC.java.child.2.java
@@ -0,0 +1 @@
+#parse("Request.java")
diff --git a/templates/front/.idea/fileTemplates/PlumeMVC.java.child.3.java b/templates/front/.idea/fileTemplates/PlumeMVC.java.child.3.java
new file mode 100644
index 00000000..e772bb91
--- /dev/null
+++ b/templates/front/.idea/fileTemplates/PlumeMVC.java.child.3.java
@@ -0,0 +1 @@
+#parse("Response.java")
diff --git a/templates/front/.idea/fileTemplates/Service.java b/templates/front/.idea/fileTemplates/Service.java
new file mode 100644
index 00000000..ecd2fe40
--- /dev/null
+++ b/templates/front/.idea/fileTemplates/Service.java
@@ -0,0 +1 @@
+#parse("Service.java")
\ No newline at end of file
diff --git "a/templates/front/.idea/fileTemplates/Story\340\274\217ext\340\274\217.stories.tsx" "b/templates/front/.idea/fileTemplates/Story\340\274\217ext\340\274\217.stories.tsx"
new file mode 100644
index 00000000..2283a420
--- /dev/null
+++ "b/templates/front/.idea/fileTemplates/Story\340\274\217ext\340\274\217.stories.tsx"
@@ -0,0 +1,16 @@
+import React from 'react';
+import type { Meta, StoryObj } from '@storybook/react';
+
+type Story = StoryObj;
+
+export const Default: Story = {
+ render: () => (
+ <${NAME} />
+ ),
+};
+
+const meta: Meta = {
+ component: ${NAME},
+};
+
+export default meta;
diff --git a/templates/front/.idea/fileTemplates/WebService.java b/templates/front/.idea/fileTemplates/WebService.java
new file mode 100644
index 00000000..19107cd0
--- /dev/null
+++ b/templates/front/.idea/fileTemplates/WebService.java
@@ -0,0 +1 @@
+#parse("WebService.java")
\ No newline at end of file
diff --git a/templates/front/.idea/fileTemplates/includes/Dao.java b/templates/front/.idea/fileTemplates/includes/Dao.java
new file mode 100644
index 00000000..4d75dfde
--- /dev/null
+++ b/templates/front/.idea/fileTemplates/includes/Dao.java
@@ -0,0 +1,30 @@
+#* ./db/dao/${Package}/${ResourceName}Dao *#
+
+#* @vtlvariable name="PACKAGE_NAME" type="java.lang.String" *#
+#* @vtlvariable name="ResourceName" type="java.lang.String" *#
+#if (${PACKAGE_NAME} != "")package ${PACKAGE_NAME};#end
+#set($DaoVariable = ${ResourceName} + "Dao")
+#set($QVariable = "Q" + ${ResourceName})
+#set($ResourceName_LowerCase = $ResourceName.substring(0,1).toLowerCase() + $ResourceName.substring(1))
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+import java.util.List;
+import com.coreoz.plume.db.querydsl.crud.CrudDaoQuerydsl;
+import com.coreoz.plume.db.querydsl.transaction.TransactionManagerQuerydsl;
+
+@Singleton
+public class ${ResourceName}Dao extends CrudDaoQuerydsl<${ResourceName}> {
+
+ @Inject
+ private ${ResourceName}Dao(TransactionManagerQuerydsl transactionManagerQuerydsl) {
+ super(transactionManagerQuerydsl, ${QVariable}.${ResourceName_LowerCase});
+ }
+
+ public List<${ResourceName}> fetch${ResourceName}s() {
+ return transactionManager.selectQuery()
+ .select(${QVariable}.${ResourceName_LowerCase})
+ .from(${QVariable}.${ResourceName_LowerCase})
+ .fetch();
+ }
+}
diff --git a/templates/front/.idea/fileTemplates/includes/Request.java b/templates/front/.idea/fileTemplates/includes/Request.java
new file mode 100644
index 00000000..16d390fe
--- /dev/null
+++ b/templates/front/.idea/fileTemplates/includes/Request.java
@@ -0,0 +1,6 @@
+#* ./webservices/api/${Package}/data/${ResourceName}Response *#
+#* @vtlvariable name="PACKAGE_NAME" type="java.lang.String" *#
+#* @vtlvariable name="ResourceName" type="java.lang.String" *#
+#if (${PACKAGE_NAME} != "")package ${PACKAGE_NAME};#end
+
+public record ${ResourceName}Request() {}
diff --git a/templates/front/.idea/fileTemplates/includes/Response.java b/templates/front/.idea/fileTemplates/includes/Response.java
new file mode 100644
index 00000000..b66c0be8
--- /dev/null
+++ b/templates/front/.idea/fileTemplates/includes/Response.java
@@ -0,0 +1,6 @@
+#* ./webservices/api/${Package}/data/${ResourceName}Response *#
+#* @vtlvariable name="PACKAGE_NAME" type="java.lang.String" *#
+#* @vtlvariable name="ResourceName" type="java.lang.String" *#
+#if (${PACKAGE_NAME} != "")package ${PACKAGE_NAME};#end
+
+public record ${ResourceName}Response() {}
diff --git a/templates/front/.idea/fileTemplates/includes/Service.java b/templates/front/.idea/fileTemplates/includes/Service.java
new file mode 100644
index 00000000..c4dfabbe
--- /dev/null
+++ b/templates/front/.idea/fileTemplates/includes/Service.java
@@ -0,0 +1,49 @@
+#* ./services/${Package}/${ResourceName}Service *#
+
+#if (${PACKAGE_NAME} != "")package ${PACKAGE_NAME};#end
+#set($ResourceName_LowerCase = $ResourceName.substring(0,1).toLowerCase() + $ResourceName.substring(1))
+#set($Dao = ${ResourceName} + "Dao")
+#set($DaoVariable = ${ResourceName_LowerCase} + "Dao")
+#set($ResourceNameRequest = ${ResourceName} + "Request")
+#set($ResourceNameRequestVariable = $ResourceNameRequest.substring(0,1).toLowerCase() + $ResourceNameRequest.substring(1))
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+import java.util.List;
+
+@Singleton
+public class ${ResourceName}Service {
+ private final $Dao $DaoVariable;
+
+ @Inject
+ private ${ResourceName}Service($Dao $DaoVariable) {
+ this.${DaoVariable} = $DaoVariable;
+ }
+
+ public List<${ResourceName}> fetch${ResourceName}s() {
+ return ${DaoVariable}.fetch${ResourceName}s();
+ }
+
+ public ${ResourceName} fetch${ResourceName}ById(Long id) {
+ return ${DaoVariable}.findById(id);
+ }
+
+ public ${ResourceName} create${ResourceName}(
+ $ResourceNameRequest $ResourceNameRequestVariable
+ ) {
+ // TODO Map request to ${ResourceName}
+ return ${DaoVariable}.save();
+ }
+
+ public ${ResourceName} update${ResourceName}(
+ Long id,
+ $ResourceNameRequest $ResourceNameRequestVariable
+ ) {
+ // TODO Map request to ${ResourceName}
+ return ${DaoVariable}.save();
+ }
+
+ public long delete${ResourceName}ById(Long id) {
+ return ${DaoVariable}.delete(id);
+ }
+}
diff --git a/templates/front/.idea/fileTemplates/includes/WebService.java b/templates/front/.idea/fileTemplates/includes/WebService.java
new file mode 100644
index 00000000..97cf57d0
--- /dev/null
+++ b/templates/front/.idea/fileTemplates/includes/WebService.java
@@ -0,0 +1,83 @@
+#* ./webservices/api/${Package}/${ResourceName}Ws *#
+#set($ResourceName_LowerCase = $ResourceName.substring(0,1).toLowerCase() + $ResourceName.substring(1))
+#set($ServiceVariable = ${ResourceName_LowerCase} + "Service")
+#set($ServiceClass = ${ResourceName} + "Service")
+#set($ResourceNameRequest = ${ResourceName} + "Request")
+#set($ResourceNameResponse = ${ResourceName} + "Response")
+#set($ResourceNamePutResponse = ${ResourceName} + "Response")
+#set($ResourceNameRequestVariable = $ResourceNameRequest.substring(0,1).toLowerCase() + $ResourceNameRequest.substring(1))
+
+#if (${PACKAGE_NAME} != "")package ${PACKAGE_NAME};#end
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+import java.util.List;
+
+@Path("/${ResourceName_LowerCase}" )
+@Tag(name = "${ResourceName}" , description = "Manage ${ResourceName_LowerCase} web-services" )
+@Consumes(MediaType.APPLICATION_JSON)
+@Produces(MediaType.APPLICATION_JSON)
+@Singleton
+// TODO Insert @RestrictTo or @PublicApi
+public class ${ResourceName}Ws {
+ private final ${ServiceClass} ${ServiceVariable};
+
+ @Inject
+ public ${ResourceName}Ws(${ServiceClass} ${ServiceVariable}) {
+ this.${ServiceVariable} = ${ServiceVariable};
+ }
+
+ @GET
+ @Operation(description = "Fetch ${ResourceName_LowerCase}s")
+ public List<$ResourceNameResponse> fetch${ResourceName}s() {
+ return ${ServiceVariable}.fetch${ResourceName}s();
+ }
+
+ @GET
+ @Path("/{id}" )
+ @Operation(description = "Fetch ${ResourceName_LowerCase} by id")
+ public $ResourceNameResponse fetch${ResourceName}(
+ @Parameter(required = true) @PathParam("id") Long id
+ ) {
+ return ${ServiceVariable}.fetch${ResourceName}ById(id);
+ }
+
+ @POST
+ @Operation(description = "Create ${ResourceName_LowerCase}")
+ public ${ResourceNameResponse} create${ResourceName}(
+ $ResourceNameRequest $ResourceNameRequestVariable
+ ) {
+ return ${ServiceVariable}.create${ResourceName}($ResourceNameRequestVariable);
+ }
+
+ @PUT
+ @Path("/{id}" )
+ @Operation(description = "Update ${ResourceName_LowerCase}")
+ public ${ResourceNamePutResponse} update${ResourceName}ById(
+ $ResourceNameRequest $ResourceNameRequestVariable,
+ @Parameter(required = true) @PathParam("id") Long id
+ ) {
+ return ${ServiceVariable}.update${ResourceName}(id, $ResourceNameRequestVariable);
+ }
+
+ @DELETE
+ @Operation(description = "Delete ${ResourceName_LowerCase} by id")
+ @Path("/{id}" )
+ public void delete${ResourceName}ById(
+ @Parameter(required = true) @PathParam("id") Long id
+ ) {
+ ${ServiceVariable}.delete${ResourceName}ById(id);
+ }
+}
\ No newline at end of file