Cette page décrit les fonctionnalités avancées et les personnalisations techniques du constructeur de format d'impression. Elle s'adresse aux administrateurs système et aux développeurs souhaitant étendre ou modifier le comportement du constructeur.
Le constructeur de format d'impression intègre un système de brouillons pour permettre des modifications sécurisées et progressives. Cette fonctionnalité est implémentée côté serveur et client pour garantir la cohérence des données.
draft_data du doctype Print Format.revision_token) pour éviter les conflits entre plusieurs éditeurs.autosave_draft dans print_format.py gère cette logique.draft_lock) pour empêcher les sauvegardes concurrentes et garantir la cohérence des données.| Méthode | Description | Paramètres |
|---|---|---|
autosave_draft | Sauvegarde automatiquement les modifications dans un brouillon. | docname (nom du format), draft_data (données du brouillon), revision_token (token de révision) |
save_and_apply | Applique le brouillon au format actif. | docname (nom du format), revision_token (token de révision) |
discard_draft | Supprime le brouillon et restaure le format actif. | docname (nom du format) |
get_draft | Récupère le brouillon actuel pour un format. | docname (nom du format) |
// Sauvegarder un brouillon
frappe.call({
method: "frappe.printing.doctype.print_format.print_format.autosave_draft",
args: {
docname: "Facture standard",
draft_data: {
sections: [/* données du brouillon */],
styles: { /* styles du brouillon */ }
},
revision_token: "abc123"
},
callback: function(r) {
if (r.message) {
console.log("Brouillon sauvegardé avec le token:", r.message.revision_token);
}
}
});
// Appliquer un brouillon
frappe.call({
method: "frappe.printing.doctype.print_format.print_format.save_and_apply",
args: {
docname: "Facture standard",
revision_token: "abc123"
},
callback: function(r) {
if (r.message) {
console.log("Brouillon appliqué avec succès");
}
}
});
Vous pouvez personnaliser le comportement du système de brouillons en modifiant les paramètres suivants dans le fichier hooks.py de votre application :
# hooks.py
app_include_js = [
"print_format_builder_overrides.js"
]
# Durée de vie des brouillons (en jours)
draft_expiry_days = 7
# Intervalle d'autosauvegarde (en secondes)
autosave_interval = 30
Le système de brouillons désactive automatiquement le suivi des versions (track_changes) pour les formats d'impression. Cela permet d'éviter la création de versions inutiles à chaque autosauvegarde, ce qui réduisait les performances et occupait inutilement de l'espace disque.
Pour réactiver le suivi des versions (non recommandé), ajoutez le code suivant dans un script personnalisé :
frappe.ui.form.on("Print Format", {
refresh: function(frm) {
frm.toggle_track_changes(true);
}
});
| Composant | Chemin | Description |
|---|---|---|
PrintFormat.vue | frappe/public/js/print_format_builder/components/editor/PrintFormat.vue | Composant principal du constructeur. |
PrintFormatSection.vue | frappe/public/js/print_format_builder/components/editor/PrintFormatSection.vue | Gère l'affichage et l'édition des sections. |
PrintFormatControls.vue | frappe/public/js/print_format_builder/components/PrintFormatControls.vue | Barre d'outils et contrôles du constructeur. |
PrintSettingsPanel.vue | frappe/public/js/print_format_builder/components/PrintSettingsPanel.vue | Panneau latéral de configuration. |
print_format_builder_overrides.js dans votre application :// print_format_builder_overrides.js
frappe.provide("frappe.print_format_builder");
frappe.print_format_builder.PrintFormatControls = class CustomPrintFormatControls extends frappe.print_format_builder.PrintFormatControls {
make() {
super.make();
this.add_custom_button();
}
add_custom_button() {
this.controls.addCustomButton({
label: __("Exporter en JSON"),
icon: "fa fa-download",
action: () => this.export_to_json()
});
}
export_to_json() {
const data = this.frm.doc;
const json = JSON.stringify(data, null, 2);
const blob = new Blob([json], { type: "application/json" });
const url = URL.createObjectURL(blob);
const a = document.createElement("a");
a.href = url;
a.download = `${this.frm.docname}.json`;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
}
};
/* print_format_builder_custom.css */
.print-format-builder {
--primary-color: #3b82f6;
--secondary-color: #1e40af;
--accent-color: #f59e0b;
}
.print-format-builder .section {
border: 1px solid var(--primary-color);
}
.print-format-builder .field-drag-handle {
background-color: var(--accent-color);
}
hooks.py :# hooks.py
app_include_css = [
"print_format_builder_custom.css"
]
custom_qr_code).Data ou Linkdoc.custom_field === "VIP").| Problème | Cause possible | Solution |
|---|---|---|
| Le constructeur ne se charge pas | Conflit avec une extension navigateur ou un script personnalisé. | Désactivez les extensions navigateur et vérifiez la console pour les erreurs JavaScript. |
| Les modifications ne sont pas sauvegardées | Problème de verrouillage ou de token de révision. | Rafraîchissez la page et vérifiez que le token de révision est correctement mis à jour. |
| Le brouillon ne s'applique pas | Conflit avec un autre utilisateur ou token de révision invalide. | Vérifiez que le token de révision correspond à celui du brouillon actuel. |
| Les champs personnalisés n'apparaissent pas | Le champ n'est pas correctement configuré dans le doctype parent. | Vérifiez que le champ est marqué comme "Imprimable" dans les propriétés du doctype. |
| L'aperçu ne se met pas à jour | Problème de cache ou de rendu. | Rafraîchissez l'aperçu ou basculez entre les modes Flux et Pages. |
site_config.json :{
"logger": {
"print_format_builder": {
"level": "debug"
}
}
}
logs/print_format_builder.log.// frappe/public/js/print_format_builder/components/blocks/CustomSignatureBlock.vue
<template>
<div class="signature-block" :style="style">
<div class="signature-label">{{ label }}</div>
<div class="signature-line"></div>
</div>
</template>
<script>
export default {
props: {
label: {
type: String,
default: "Signature"
},
style: {
type: Object,
default: () => ({})
}
}
}
</script>
<style scoped>
.signature-block {
margin: 10px 0;
padding: 10px;
border-top: 1px dashed #ccc;
}
.signature-label {
font-size: 12px;
color: #666;
}
.signature-line {
height: 1px;
background-color: #000;
margin-top: 20px;
}
</style>
// print_format_builder_overrides.js
frappe.provide("frappe.print_format_builder");
frappe.print_format_builder.blocks = {
...frappe.print_format_builder.blocks,
"Signature": {
label: __("Signature"),
component: () => import("./components/blocks/CustomSignatureBlock.vue"),
icon: "fa fa-pencil"
}
};
hooks.py :# hooks.py
app_include_js = [
"print_format_builder_overrides.js"
]
custom_signature), modifiez le composant comme suit :// CustomSignatureBlock.vue
<template>
<div class="signature-block" :style="style">
<div class="signature-label">{{ label }}</div>
<div class="signature-line" v-if="!doc[fieldname]"></div>
<img :src="doc[fieldname]" v-if="doc[fieldname]" class="signature-image" />
</div>
</template>
<script>
export default {
props: {
label: {
type: String,
default: "Signature"
},
style: {
type: Object,
default: () => ({})
},
fieldname: {
type: String,
default: "custom_signature"
},
doc: {
type: Object,
default: () => ({})
}
}
}
</script>
<style scoped>
.signature-image {
max-width: 200px;
max-height: 100px;
}
</style>
print_format_builder_overrides.js :frappe.print_format_builder.blocks["Signature"] = {
label: __("Signature"),
component: () => import("./components/blocks/CustomSignatureBlock.vue"),
icon: "fa fa-pencil",
props: {
fieldname: "custom_signature"
}
};