[{"data":1,"prerenderedAt":2473},["ShallowReactive",2],{"\u002Fnext\u002Fdodock\u002Fdeveloppeurs\u002Fhooks-rapprochement-bancaire":3,"section:\u002Fnext\u002Fdodock\u002Fdeveloppeurs\u002Fhooks-rapprochement-bancaire":2472},{"id":4,"title":5,"body":6,"description":2463,"extension":2464,"meta":2465,"navigation":799,"path":2468,"seo":2469,"stem":2470,"__hash__":2471},"docs\u002F2.next\u002F3.dodock\u002F10.developpeurs\u002Fhooks-rapprochement-bancaire.md","Hooks de rapprochement bancaire",{"type":7,"value":8,"toc":2437},"minimark",[9,13,30,38,54,198,203,260,266,269,304,322,327,334,619,645,649,655,757,771,775,1014,1021,1027,1030,1044,1084,1094,1097,1109,1123,1134,1140,1143,1157,1162,1202,1205,1211,1218,1232,1238,1244,1250,1264,1301,1311,1317,1329,1357,1404,1431,1450,1456,1470,1484,1490,1629,1721,1727,1740,1746,1760,1780,1831,1837,1844,1858,1865,2212,2267,2285,2302,2323,2384,2399,2403,2433],[10,11,5],"h1",{"id":12},"hooks-de-rapprochement-bancaire",[14,15,18],"callout",{"color":16,"icon":17},"amber","i-mdi-progress-wrench",[19,20,21,22,29],"p",{},"Ces hooks sont en cours d'implémentation (",[23,24,28],"a",{"href":25,"rel":26},"https:\u002F\u002Fgitlab.com\u002Fdokos\u002Fdokos\u002F-\u002Fissues\u002F504",[27],"nofollow","dokos\u002Fdokos#504","). Cette page décrit le contrat prévu. Elle sera publiée avec la version qui les contient.",[19,31,32,33,37],{},"Une application peut étendre la page ",[23,34,36],{"href":35},"\u002Fnext\u002Fdokos\u002Fcomptabilite\u002Frapprochement-bancaire","Rapprochement bancaire"," sans modifier Dokos : ajouter un type de document à rapprocher, changer le classement des documents proposés, rapprocher automatiquement ses propres opérations, réagir à un rapprochement, ajouter des actions, des colonnes et des panneaux.",[19,39,40,41,45,46,49,50,53],{},"Tous les hooks se déclarent dans le fichier ",[42,43,44],"code",{},"hooks.py"," de l'application. Dokos les lit avec ",[42,47,48],{},"frappe.get_hooks()"," et charge chaque chemin avec ",[42,51,52],{},"frappe.get_attr()",".",[55,56,57,73],"table",{},[58,59,60],"thead",{},[61,62,63,67,70],"tr",{},[64,65,66],"th",{},"Hook",[64,68,69],{},"Valeur",[64,71,72],{},"Rôle",[74,75,76,93,106,118,130,142,157,173,185],"tbody",{},[61,77,78,84,90],{},[79,80,81],"td",{},[42,82,83],{},"bank_reconciliation_providers",[79,85,86,87],{},"Dictionnaire ",[42,88,89],{},"{doctype: chemin de classe}",[79,91,92],{},"Ajoute un type de document à rapprocher",[61,94,95,100,103],{},[79,96,97],{},[42,98,99],{},"bank_reconciliation_match_rules",[79,101,102],{},"Liste de chemins de fonctions",[79,104,105],{},"Modifie le score des documents proposés",[61,107,108,113,115],{},[79,109,110],{},[42,111,112],{},"auto_reconciliation_methods",[79,114,102],{},[79,116,117],{},"Rapproche une transaction pendant le rapprochement automatique",[61,119,120,125,127],{},[79,121,122],{},[42,123,124],{},"bank_reconciliation_batch_reconcilers",[79,126,102],{},[79,128,129],{},"Rapproche un lot de transactions (virements groupés des prestataires de paiement)",[61,131,132,137,139],{},[79,133,134],{},[42,135,136],{},"bank_reconciliation_validators",[79,138,102],{},[79,140,141],{},"Refuse un rapprochement avant son enregistrement",[61,143,144,149,154],{},[79,145,146],{},[42,147,148],{},"bank_reconciliation_events",[79,150,86,151],{},[42,152,153],{},"{on_allocate: [...], on_deallocate: [...]}",[79,155,156],{},"Réagit à l'ajout ou au retrait d'une ligne de rapprochement",[61,158,159,164,166],{},[79,160,161],{},[42,162,163],{},"bank_reconciliation_actions",[79,165,102],{},[79,167,168,169],{},"Ajoute une action sous le bouton ",[170,171,172],"strong",{},"Rapprocher",[61,174,175,180,182],{},[79,176,177],{},[42,178,179],{},"bank_reconciliation_transaction_columns",[79,181,102],{},[79,183,184],{},"Ajoute des colonnes à la liste des transactions",[61,186,187,192,195],{},[79,188,189],{},[42,190,191],{},"bank_reconciliation_js",[79,193,194],{},"Liste de bundles JavaScript",[79,196,197],{},"Charge le JavaScript de l'application dans la page (panneaux, badges)",[199,200,202],"h2",{"id":201},"périmètre","Périmètre",[204,205,206,218,225,245],"ul",{},[207,208,209,210,213,214,217],"li",{},"Les hooks d'interface (types de documents en onglets, actions, colonnes, JavaScript) s'appliquent ",[170,211,212],{},"uniquement à la page Rapprochement bancaire de Dokos"," (",[42,215,216],{},"\u002Fdesk\u002Fbank-reconciliation",").",[207,219,220,221,224],{},"Le panneau latéral de la liste des ",[170,222,223],{},"Transactions bancaires"," ne reçoit pas ces extensions. Il continue de fonctionner tel quel.",[207,226,227,228,232,233,236,237,240,241,53],{},"L'",[23,229,231],{"href":230},"\u002Fnext\u002Fdokos\u002Fcomptabilite\u002Foutil-rapprochement-bancaire","outil de rapprochement bancaire"," hérité d'ERPNext et l'application ",[42,234,235],{},"\u002Fbanking"," ne sont pas concernés. Ils gardent le hook ",[42,238,239],{},"get_matching_queries",". Pour ajouter un type de pièce à leur dialogue « Créer une pièce », voir ",[23,242,244],{"href":243},"\u002Fnext\u002Fdodock\u002Fdeveloppeurs\u002Frapprochement-bancaire-types-de-pieces","Types de pièces extensibles",[207,246,247,248,251,252,255,256,259],{},"Les fournisseurs (mise à jour du montant non rapproché, date de compensation) et les événements ",[42,249,250],{},"on_allocate"," \u002F ",[42,253,254],{},"on_deallocate"," sont appelés par la ",[170,257,258],{},"Transaction bancaire"," elle-même. Ils s'appliquent donc quel que soit l'écran qui a fait le rapprochement.",[199,261,263,265],{"id":262},"bank_reconciliation_providers-ajouter-un-type-de-document",[42,264,83],{}," : ajouter un type de document",[19,267,268],{},"Un fournisseur est une classe qui décrit un type de document pour le rapprochement : où trouver les documents candidats, quel tiers, quel compte, quel montant reste à rapprocher. Les types natifs (Écriture de paiement, Écriture de journal, Facture de vente, Facture d'achat) utilisent le même mécanisme.",[270,271,276],"pre",{"className":272,"code":273,"language":274,"meta":275,"style":275},"language-python shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","# mon_app\u002Fhooks.py\nbank_reconciliation_providers = {\n    \"Loan Repayment\": \"mon_app.rapprochement.LoanRepaymentProvider\",\n}\n","python","",[42,277,278,286,292,298],{"__ignoreMap":275},[279,280,283],"span",{"class":281,"line":282},"line",1,[279,284,285],{},"# mon_app\u002Fhooks.py\n",[279,287,289],{"class":281,"line":288},2,[279,290,291],{},"bank_reconciliation_providers = {\n",[279,293,295],{"class":281,"line":294},3,[279,296,297],{},"    \"Loan Repayment\": \"mon_app.rapprochement.LoanRepaymentProvider\",\n",[279,299,301],{"class":281,"line":300},4,[279,302,303],{},"}\n",[19,305,306,307,310,311,314,315,318,319,53],{},"Si deux applications déclarent un fournisseur pour le même type, la dernière application installée l'emporte. Un type listé dans l'ancien hook ",[42,308,309],{},"bank_reconciliation_doctypes"," sans fournisseur reçoit un fournisseur générique, qui lit les champs ",[42,312,313],{},"posting_date",", ",[42,316,317],{},"unreconciled_amount"," et ",[42,320,321],{},"clearance_date",[323,324,326],"h3",{"id":325},"attributs-et-méthodes","Attributs et méthodes",[19,328,329,330,333],{},"La classe hérite de ",[42,331,332],{},"erpnext.accounts.bank_reconciliation.provider.BankReconciliationProvider",". La classe de base fournit un comportement par défaut pour la plupart des méthodes.",[55,335,336,348],{},[58,337,338],{},[61,339,340,343,346],{},[64,341,342],{},"Élément",[64,344,345],{},"Type",[64,347,72],{},[74,349,350,365,379,399,416,437,459,474,489,504,518,535,552,567,582,596],{},[61,351,352,357,362],{},[79,353,354],{},[42,355,356],{},"doctype",[79,358,359],{},[42,360,361],{},"str",[79,363,364],{},"Type de document",[61,366,367,372,376],{},[79,368,369],{},[42,370,371],{},"label",[79,373,374],{},[42,375,361],{},[79,377,378],{},"Libellé de l'onglet (par défaut, le nom traduit du type)",[61,380,381,392,396],{},[79,382,383,314,386,314,389],{},[42,384,385],{},"party_type",[42,387,388],{},"party_field",[42,390,391],{},"party_name_field",[79,393,394],{},[42,395,361],{},[79,397,398],{},"Type de tiers et champs du tiers",[61,400,401,409,413],{},[79,402,403,314,406],{},[42,404,405],{},"reference_field",[42,407,408],{},"reference_date_field",[79,410,411],{},[42,412,361],{},[79,414,415],{},"Champ affiché comme référence, champ de date",[61,417,418,423,428],{},[79,419,420],{},[42,421,422],{},"directions",[79,424,425],{},[42,426,427],{},"tuple",[79,429,430,314,433,436],{},[42,431,432],{},"(\"in\",)",[42,434,435],{},"(\"out\",)"," ou les deux : entrées ou sorties d'argent proposées",[61,438,439,444,449],{},[79,440,441],{},[42,442,443],{},"creates_payment_entry",[79,445,446],{},[42,447,448],{},"bool",[79,450,451,454,455,458],{},[42,452,453],{},"True"," : le rapprochement crée une ",[170,456,457],{},"Écriture de paiement"," (cas des factures)",[61,460,461,466,471],{},[79,462,463],{},[42,464,465],{},"sort_order",[79,467,468],{},[42,469,470],{},"int",[79,472,473],{},"Position de l'onglet (les types natifs utilisent 10 à 40)",[61,475,476,481,486],{},[79,477,478],{},[42,479,480],{},"columns",[79,482,483],{},[42,484,485],{},"list[dict]",[79,487,488],{},"Colonnes supplémentaires du tableau des documents",[61,490,491,496,501],{},[79,492,493],{},[42,494,495],{},"get_candidates(filters)",[79,497,498],{},[42,499,500],{},"-> list[dict]",[79,502,503],{},"Documents candidats (obligatoire)",[61,505,506,511,515],{},[79,507,508],{},[42,509,510],{},"get_candidates_by_name(names)",[79,512,513],{},[42,514,500],{},[79,516,517],{},"Documents candidats par nom (historique, rapprochement automatique)",[61,519,520,525,530],{},[79,521,522],{},[42,523,524],{},"get_party_account(doc)",[79,526,527],{},[42,528,529],{},"-> str",[79,531,532,533],{},"Compte de tiers, si ",[42,534,443],{},[61,536,537,542,547],{},[79,538,539],{},[42,540,541],{},"get_outstanding_amount(doc)",[79,543,544],{},[42,545,546],{},"-> float",[79,548,549,550],{},"Montant restant dû, si ",[42,551,443],{},[61,553,554,559,564],{},[79,555,556],{},[42,557,558],{},"update_unreconciled_amount(name, bank_account_head, delta)",[79,560,561],{},[42,562,563],{},"-> None",[79,565,566],{},"Met à jour le montant non rapproché du document",[61,568,569,574,579],{},[79,570,571],{},[42,572,573],{},"get_payment_type(name, bank_account_head)",[79,575,576],{},[42,577,578],{},"-> \"Debit\" | \"Credit\"",[79,580,581],{},"Sens de la ligne de rapprochement",[61,583,584,589,593],{},[79,585,586],{},[42,587,588],{},"set_clearance_date(name, date)",[79,590,591],{},[42,592,563],{},[79,594,595],{},"Écrit ou efface la date de compensation",[61,597,598,603,608],{},[79,599,600],{},[42,601,602],{},"make_new_document(transactions)",[79,604,605],{},[42,606,607],{},"-> Document | None",[79,609,610,611,614,615,618],{},"Prépare le document du bouton ",[170,612,613],{},"Créer"," ; ",[42,616,617],{},"None"," ouvre un formulaire vide",[19,620,621,622,625,626,629,630,633,634,637,638,641,642,217],{},"L'objet ",[42,623,624],{},"self.context"," donne la ou les transactions sélectionnées (",[42,627,628],{},"bank_transactions","), le compte bancaire (",[42,631,632],{},"bank_account","), son compte comptable (",[42,635,636],{},"bank_account_head","), la société, la devise, le montant signé (",[42,639,640],{},"amount",", positif pour une entrée) et le sens (",[42,643,644],{},"direction",[323,646,648],{"id":647},"forme-dun-document-candidat","Forme d'un document candidat",[19,650,651,654],{},[42,652,653],{},"get_candidates"," renvoie une liste de dictionnaires :",[270,656,658],{"className":272,"code":657,"language":274,"meta":275,"style":275},"{\n    \"doctype\": \"Loan Repayment\",\n    \"name\": \"LR-0001\",\n    \"date\": \"2026-10-03\",\n    \"amount\": -120.0,              # signé, devise du compte bancaire ; négatif = sortie\n    \"unreconciled_amount\": 120.0,  # montant encore rapprochable\n    \"currency\": \"EUR\",\n    \"party\": \"SUP-0001\",\n    \"party_name\": \"Banque Exemple\",\n    \"reference_string\": \"LR-0001: contrat 42\",\n    # facultatif\n    \"reference_date\": \"2026-10-03\",\n    \"mode_of_payment\": \"Virement\",\n    \"score\": 0,\n    \"match_reasons\": [],\n    \"extra\": {},                   # données libres pour vos colonnes et panneaux\n}\n",[42,659,660,665,670,675,680,686,692,698,704,710,716,722,728,734,740,746,752],{"__ignoreMap":275},[279,661,662],{"class":281,"line":282},[279,663,664],{},"{\n",[279,666,667],{"class":281,"line":288},[279,668,669],{},"    \"doctype\": \"Loan Repayment\",\n",[279,671,672],{"class":281,"line":294},[279,673,674],{},"    \"name\": \"LR-0001\",\n",[279,676,677],{"class":281,"line":300},[279,678,679],{},"    \"date\": \"2026-10-03\",\n",[279,681,683],{"class":281,"line":682},5,[279,684,685],{},"    \"amount\": -120.0,              # signé, devise du compte bancaire ; négatif = sortie\n",[279,687,689],{"class":281,"line":688},6,[279,690,691],{},"    \"unreconciled_amount\": 120.0,  # montant encore rapprochable\n",[279,693,695],{"class":281,"line":694},7,[279,696,697],{},"    \"currency\": \"EUR\",\n",[279,699,701],{"class":281,"line":700},8,[279,702,703],{},"    \"party\": \"SUP-0001\",\n",[279,705,707],{"class":281,"line":706},9,[279,708,709],{},"    \"party_name\": \"Banque Exemple\",\n",[279,711,713],{"class":281,"line":712},10,[279,714,715],{},"    \"reference_string\": \"LR-0001: contrat 42\",\n",[279,717,719],{"class":281,"line":718},11,[279,720,721],{},"    # facultatif\n",[279,723,725],{"class":281,"line":724},12,[279,726,727],{},"    \"reference_date\": \"2026-10-03\",\n",[279,729,731],{"class":281,"line":730},13,[279,732,733],{},"    \"mode_of_payment\": \"Virement\",\n",[279,735,737],{"class":281,"line":736},14,[279,738,739],{},"    \"score\": 0,\n",[279,741,743],{"class":281,"line":742},15,[279,744,745],{},"    \"match_reasons\": [],\n",[279,747,749],{"class":281,"line":748},16,[279,750,751],{},"    \"extra\": {},                   # données libres pour vos colonnes et panneaux\n",[279,753,755],{"class":281,"line":754},17,[279,756,303],{},[19,758,759,760,763,764,767,768,53],{},"Utilisez ",[42,761,762],{},"frappe.get_list"," : les permissions de l'utilisateur s'appliquent. Dokos retire aussi les lignes que l'utilisateur ne peut pas lire, et ignore un fournisseur dont ",[42,765,766],{},"is_permitted()"," renvoie ",[42,769,770],{},"False",[323,772,774],{"id":773},"exemple","Exemple",[270,776,778],{"className":272,"code":777,"language":274,"meta":275,"style":275},"# mon_app\u002Frapprochement.py\nimport frappe\nfrom erpnext.accounts.bank_reconciliation.provider import BankReconciliationProvider\n\n\nclass LoanRepaymentProvider(BankReconciliationProvider):\n    # « Loan Repayment » est un DocType fictif de l'application, avec les champs\n    # unreconciled_amount et clearance_date.\n    doctype = \"Loan Repayment\"\n    party_type = \"Supplier\"\n    party_field = \"lender\"\n    party_name_field = \"lender_name\"\n    reference_field = \"contract_number\"\n    reference_date_field = \"due_date\"\n    directions = (\"out\",)\n    columns = [{\"field\": \"extra.contract_number\", \"label\": \"Contrat\", \"format\": \"Data\"}]\n\n    def get_candidates(self, filters):\n        rows = frappe.get_list(\n            \"Loan Repayment\",\n            filters={\n                \"docstatus\": 1,\n                \"company\": self.context.company,\n                \"unreconciled_amount\": (\"!=\", 0),\n            },\n            fields=[\"name\", \"due_date\", \"unreconciled_amount\", \"lender\", \"lender_name\", \"contract_number\"],\n        )\n        return [\n            {\n                \"doctype\": self.doctype,\n                \"name\": r.name,\n                \"date\": r.due_date,\n                \"amount\": -r.unreconciled_amount,\n                \"unreconciled_amount\": r.unreconciled_amount,\n                \"currency\": self.context.currency,\n                \"party\": r.lender,\n                \"party_name\": r.lender_name,\n                \"reference_string\": f\"{r.name}: {r.contract_number}\",\n                \"extra\": {\"contract_number\": r.contract_number},\n            }\n            for r in rows\n        ]\n",[42,779,780,785,790,795,801,805,810,815,820,825,830,835,840,845,850,855,860,864,870,876,882,888,894,900,906,912,918,924,930,936,942,948,954,960,966,972,978,984,990,996,1002,1008],{"__ignoreMap":275},[279,781,782],{"class":281,"line":282},[279,783,784],{},"# mon_app\u002Frapprochement.py\n",[279,786,787],{"class":281,"line":288},[279,788,789],{},"import frappe\n",[279,791,792],{"class":281,"line":294},[279,793,794],{},"from erpnext.accounts.bank_reconciliation.provider import BankReconciliationProvider\n",[279,796,797],{"class":281,"line":300},[279,798,800],{"emptyLinePlaceholder":799},true,"\n",[279,802,803],{"class":281,"line":682},[279,804,800],{"emptyLinePlaceholder":799},[279,806,807],{"class":281,"line":688},[279,808,809],{},"class LoanRepaymentProvider(BankReconciliationProvider):\n",[279,811,812],{"class":281,"line":694},[279,813,814],{},"    # « Loan Repayment » est un DocType fictif de l'application, avec les champs\n",[279,816,817],{"class":281,"line":700},[279,818,819],{},"    # unreconciled_amount et clearance_date.\n",[279,821,822],{"class":281,"line":706},[279,823,824],{},"    doctype = \"Loan Repayment\"\n",[279,826,827],{"class":281,"line":712},[279,828,829],{},"    party_type = \"Supplier\"\n",[279,831,832],{"class":281,"line":718},[279,833,834],{},"    party_field = \"lender\"\n",[279,836,837],{"class":281,"line":724},[279,838,839],{},"    party_name_field = \"lender_name\"\n",[279,841,842],{"class":281,"line":730},[279,843,844],{},"    reference_field = \"contract_number\"\n",[279,846,847],{"class":281,"line":736},[279,848,849],{},"    reference_date_field = \"due_date\"\n",[279,851,852],{"class":281,"line":742},[279,853,854],{},"    directions = (\"out\",)\n",[279,856,857],{"class":281,"line":748},[279,858,859],{},"    columns = [{\"field\": \"extra.contract_number\", \"label\": \"Contrat\", \"format\": \"Data\"}]\n",[279,861,862],{"class":281,"line":754},[279,863,800],{"emptyLinePlaceholder":799},[279,865,867],{"class":281,"line":866},18,[279,868,869],{},"    def get_candidates(self, filters):\n",[279,871,873],{"class":281,"line":872},19,[279,874,875],{},"        rows = frappe.get_list(\n",[279,877,879],{"class":281,"line":878},20,[279,880,881],{},"            \"Loan Repayment\",\n",[279,883,885],{"class":281,"line":884},21,[279,886,887],{},"            filters={\n",[279,889,891],{"class":281,"line":890},22,[279,892,893],{},"                \"docstatus\": 1,\n",[279,895,897],{"class":281,"line":896},23,[279,898,899],{},"                \"company\": self.context.company,\n",[279,901,903],{"class":281,"line":902},24,[279,904,905],{},"                \"unreconciled_amount\": (\"!=\", 0),\n",[279,907,909],{"class":281,"line":908},25,[279,910,911],{},"            },\n",[279,913,915],{"class":281,"line":914},26,[279,916,917],{},"            fields=[\"name\", \"due_date\", \"unreconciled_amount\", \"lender\", \"lender_name\", \"contract_number\"],\n",[279,919,921],{"class":281,"line":920},27,[279,922,923],{},"        )\n",[279,925,927],{"class":281,"line":926},28,[279,928,929],{},"        return [\n",[279,931,933],{"class":281,"line":932},29,[279,934,935],{},"            {\n",[279,937,939],{"class":281,"line":938},30,[279,940,941],{},"                \"doctype\": self.doctype,\n",[279,943,945],{"class":281,"line":944},31,[279,946,947],{},"                \"name\": r.name,\n",[279,949,951],{"class":281,"line":950},32,[279,952,953],{},"                \"date\": r.due_date,\n",[279,955,957],{"class":281,"line":956},33,[279,958,959],{},"                \"amount\": -r.unreconciled_amount,\n",[279,961,963],{"class":281,"line":962},34,[279,964,965],{},"                \"unreconciled_amount\": r.unreconciled_amount,\n",[279,967,969],{"class":281,"line":968},35,[279,970,971],{},"                \"currency\": self.context.currency,\n",[279,973,975],{"class":281,"line":974},36,[279,976,977],{},"                \"party\": r.lender,\n",[279,979,981],{"class":281,"line":980},37,[279,982,983],{},"                \"party_name\": r.lender_name,\n",[279,985,987],{"class":281,"line":986},38,[279,988,989],{},"                \"reference_string\": f\"{r.name}: {r.contract_number}\",\n",[279,991,993],{"class":281,"line":992},39,[279,994,995],{},"                \"extra\": {\"contract_number\": r.contract_number},\n",[279,997,999],{"class":281,"line":998},40,[279,1000,1001],{},"            }\n",[279,1003,1005],{"class":281,"line":1004},41,[279,1006,1007],{},"            for r in rows\n",[279,1009,1011],{"class":281,"line":1010},42,[279,1012,1013],{},"        ]\n",[19,1015,1016,1017,1020],{},"Un onglet ",[170,1018,1019],{},"Loan Repayment"," apparaît dans le panneau des documents quand la transaction sélectionnée est une sortie d'argent.",[199,1022,1024,1026],{"id":1023},"bank_reconciliation_match_rules-classer-les-documents-proposés",[42,1025,99],{}," : classer les documents proposés",[19,1028,1029],{},"Une règle modifie le score (0 à 100) des documents candidats et explique pourquoi.",[270,1031,1033],{"className":272,"code":1032,"language":274,"meta":275,"style":275},"# mon_app\u002Fhooks.py\nbank_reconciliation_match_rules = [\"mon_app.rapprochement.numero_de_contrat\"]\n",[42,1034,1035,1039],{"__ignoreMap":275},[279,1036,1037],{"class":281,"line":282},[279,1038,285],{},[279,1040,1041],{"class":281,"line":288},[279,1042,1043],{},"bank_reconciliation_match_rules = [\"mon_app.rapprochement.numero_de_contrat\"]\n",[270,1045,1047],{"className":272,"code":1046,"language":274,"meta":275,"style":275},"def numero_de_contrat(context, candidates):\n    libelle = \" \".join(t.get(\"description\") or \"\" for t in context.bank_transactions)\n    for c in candidates:\n        numero = c.get(\"extra\", {}).get(\"contract_number\")\n        if numero and numero in libelle:\n            c[\"score\"] = max(c.get(\"score\", 0), 95)\n            c.setdefault(\"match_reasons\", []).append(\"Numéro de contrat trouvé dans le libellé\")\n",[42,1048,1049,1054,1059,1064,1069,1074,1079],{"__ignoreMap":275},[279,1050,1051],{"class":281,"line":282},[279,1052,1053],{},"def numero_de_contrat(context, candidates):\n",[279,1055,1056],{"class":281,"line":288},[279,1057,1058],{},"    libelle = \" \".join(t.get(\"description\") or \"\" for t in context.bank_transactions)\n",[279,1060,1061],{"class":281,"line":294},[279,1062,1063],{},"    for c in candidates:\n",[279,1065,1066],{"class":281,"line":300},[279,1067,1068],{},"        numero = c.get(\"extra\", {}).get(\"contract_number\")\n",[279,1070,1071],{"class":281,"line":682},[279,1072,1073],{},"        if numero and numero in libelle:\n",[279,1075,1076],{"class":281,"line":688},[279,1077,1078],{},"            c[\"score\"] = max(c.get(\"score\", 0), 95)\n",[279,1080,1081],{"class":281,"line":694},[279,1082,1083],{},"            c.setdefault(\"match_reasons\", []).append(\"Numéro de contrat trouvé dans le libellé\")\n",[19,1085,1086,1087,1090,1091,1093],{},"Signature : ",[42,1088,1089],{},"fn(context, candidates) -> list[dict] | None",". Renvoyez une nouvelle liste pour retirer des candidats, ou ",[42,1092,617],{}," pour garder la liste modifiée sur place.",[19,1095,1096],{},"Ordre d'exécution :",[1098,1099,1100,1103,1106],"ol",{},[207,1101,1102],{},"Dokos applique ses règles natives : montant identique, historique des rapprochements, tiers, date la plus proche.",[207,1104,1105],{},"Dokos appelle les règles des applications, dans l'ordre des hooks.",[207,1107,1108],{},"Dokos trie les candidats par score, puis par date.",[19,1110,1111,1114,1115,1118,1119,1122],{},[170,1112,1113],{},"Présélection"," : si une règle d'application a changé un score, le premier document n'est présélectionné que si son score est ",[170,1116,1117],{},"d'au moins 80"," et a ",[170,1120,1121],{},"au moins 10 points d'avance"," sur le suivant. Sinon, aucun document n'est présélectionné. Une règle propose, elle ne peut pas forcer la sélection. Si aucune règle d'application ne change de score, la présélection native reste inchangée.",[19,1124,1125,1126,1129,1130,1133],{},"Avec ",[170,1127,1128],{},"Afficher la liste complète",", les règles ne servent qu'à remplir ",[42,1131,1132],{},"match_reasons"," : rien n'est retiré ni présélectionné.",[199,1135,1137,1139],{"id":1136},"auto_reconciliation_methods-rapprochement-automatique",[42,1138,112],{}," : rapprochement automatique",[19,1141,1142],{},"Le bouton de rapprochement automatique appelle chaque fonction de ce hook pour chaque transaction, avant la recherche native.",[270,1144,1146],{"className":272,"code":1145,"language":274,"meta":275,"style":275},"# mon_app\u002Fhooks.py\nauto_reconciliation_methods = [\"mon_app.rapprochement.par_mandat\"]\n",[42,1147,1148,1152],{"__ignoreMap":275},[279,1149,1150],{"class":281,"line":282},[279,1151,285],{},[279,1153,1154],{"class":281,"line":288},[279,1155,1156],{},"auto_reconciliation_methods = [\"mon_app.rapprochement.par_mandat\"]\n",[19,1158,1086,1159,53],{},[42,1160,1161],{},"fn(bank_transaction) -> bool | list[dict] | None",[55,1163,1164,1174],{},[58,1165,1166],{},[61,1167,1168,1171],{},[64,1169,1170],{},"Valeur renvoyée",[64,1172,1173],{},"Effet",[74,1175,1176,1185,1193],{},[61,1177,1178,1182],{},[79,1179,1180],{},[42,1181,453],{},[79,1183,1184],{},"La fonction a rapproché la transaction ; Dokos passe à la suivante",[61,1186,1187,1190],{},[79,1188,1189],{},"Liste de documents candidats",[79,1191,1192],{},"Dokos les ajoute à sa propre recherche (ils peuvent donner une proposition à valider si plusieurs tiers sont concernés)",[61,1194,1195,1199],{},[79,1196,1197],{},[42,1198,617],{},[79,1200,1201],{},"Rien trouvé ; Dokos continue normalement",[19,1203,1204],{},"Chaque transaction est traitée dans son propre point de sauvegarde : une exception annule seulement cette transaction, qui est comptée comme « laissée au rapprochement manuel ».",[199,1206,1208,1210],{"id":1207},"bank_reconciliation_batch_reconcilers-virements-groupés",[42,1209,124],{}," : virements groupés",[19,1212,1213,1214,1217],{},"Après le traitement transaction par transaction, le rapprochement automatique appelle chaque fonction de ce hook avec ",[170,1215,1216],{},"toutes"," les transactions. Dokos y déclare lui-même le rapprochement des virements Stripe, GoCardless et Stancer.",[270,1219,1221],{"className":272,"code":1220,"language":274,"meta":275,"style":275},"# mon_app\u002Fhooks.py\nbank_reconciliation_batch_reconcilers = [\"mon_app.rapprochement.virements_prestataire\"]\n",[42,1222,1223,1227],{"__ignoreMap":275},[279,1224,1225],{"class":281,"line":282},[279,1226,285],{},[279,1228,1229],{"class":281,"line":288},[279,1230,1231],{},"bank_reconciliation_batch_reconcilers = [\"mon_app.rapprochement.virements_prestataire\"]\n",[19,1233,1086,1234,1237],{},[42,1235,1236],{},"fn(bank_transactions: list) -> int | None",". Renvoyez le nombre de transactions rapprochées : il est ajouté au résumé affiché à l'utilisateur. Chaque fonction tourne dans son propre point de sauvegarde ; une erreur n'empêche pas les suivantes.",[199,1239,1241,1243],{"id":1240},"bank_reconciliation_validators-refuser-un-rapprochement",[42,1242,136],{}," : refuser un rapprochement",[19,1245,1246,1247,1249],{},"Un validateur est appelé quand l'utilisateur clique sur ",[170,1248,172],{},", après les contrôles de Dokos (même tiers, même société…), et lors d'un rapprochement depuis un ordre de paiement.",[270,1251,1253],{"className":272,"code":1252,"language":274,"meta":275,"style":275},"# mon_app\u002Fhooks.py\nbank_reconciliation_validators = [\"mon_app.rapprochement.valider\"]\n",[42,1254,1255,1259],{"__ignoreMap":275},[279,1256,1257],{"class":281,"line":282},[279,1258,285],{},[279,1260,1261],{"class":281,"line":288},[279,1262,1263],{},"bank_reconciliation_validators = [\"mon_app.rapprochement.valider\"]\n",[270,1265,1267],{"className":272,"code":1266,"language":274,"meta":275,"style":275},"import frappe\nfrom frappe import _\n\n\ndef valider(context, documents):\n    if any(d[\"doctype\"] == \"Loan Repayment\" for d in documents) and len(context.bank_transactions) > 1:\n        frappe.throw(_(\"Un remboursement de prêt se rapproche avec une seule transaction.\"))\n",[42,1268,1269,1273,1278,1282,1286,1291,1296],{"__ignoreMap":275},[279,1270,1271],{"class":281,"line":282},[279,1272,789],{},[279,1274,1275],{"class":281,"line":288},[279,1276,1277],{},"from frappe import _\n",[279,1279,1280],{"class":281,"line":294},[279,1281,800],{"emptyLinePlaceholder":799},[279,1283,1284],{"class":281,"line":300},[279,1285,800],{"emptyLinePlaceholder":799},[279,1287,1288],{"class":281,"line":682},[279,1289,1290],{},"def valider(context, documents):\n",[279,1292,1293],{"class":281,"line":688},[279,1294,1295],{},"    if any(d[\"doctype\"] == \"Loan Repayment\" for d in documents) and len(context.bank_transactions) > 1:\n",[279,1297,1298],{"class":281,"line":694},[279,1299,1300],{},"        frappe.throw(_(\"Un remboursement de prêt se rapproche avec une seule transaction.\"))\n",[19,1302,1086,1303,1306,1307,1310],{},[42,1304,1305],{},"fn(context, documents) -> None",". Levez une erreur (",[42,1308,1309],{},"frappe.throw",") pour refuser : rien n'est enregistré et l'utilisateur voit le message.",[199,1312,1314,1316],{"id":1313},"bank_reconciliation_events-réagir-à-un-rapprochement",[42,1315,148],{}," : réagir à un rapprochement",[19,1318,1319,1320,1322,1323,1325,1326,1328],{},"Ces événements sont appelés par la ",[170,1321,258],{}," à chaque ligne de rapprochement ajoutée (",[42,1324,250],{},") ou retirée (",[42,1327,254],{},"), quel que soit l'écran : rapprochement manuel ou automatique, ordre de paiement, prélèvement SEPA, annulation du rapprochement, annulation de la transaction.",[270,1330,1332],{"className":272,"code":1331,"language":274,"meta":275,"style":275},"# mon_app\u002Fhooks.py\nbank_reconciliation_events = {\n    \"on_allocate\": [\"mon_app.rapprochement.marquer_paye\"],\n    \"on_deallocate\": [\"mon_app.rapprochement.marquer_impaye\"],\n}\n",[42,1333,1334,1338,1343,1348,1353],{"__ignoreMap":275},[279,1335,1336],{"class":281,"line":282},[279,1337,285],{},[279,1339,1340],{"class":281,"line":288},[279,1341,1342],{},"bank_reconciliation_events = {\n",[279,1344,1345],{"class":281,"line":294},[279,1346,1347],{},"    \"on_allocate\": [\"mon_app.rapprochement.marquer_paye\"],\n",[279,1349,1350],{"class":281,"line":300},[279,1351,1352],{},"    \"on_deallocate\": [\"mon_app.rapprochement.marquer_impaye\"],\n",[279,1354,1355],{"class":281,"line":682},[279,1356,303],{},[270,1358,1360],{"className":272,"code":1359,"language":274,"meta":275,"style":275},"import frappe\n\n\ndef marquer_paye(bank_transaction, row):\n    if row.payment_document != \"Loan Repayment\":\n        return\n    frappe.get_doc(\"Loan Repayment\", row.payment_entry).set_status(update=True)\n    # Appel externe : seulement après la validation de la transaction\n    frappe.enqueue(\"mon_app.notifications.preteur\", remboursement=row.payment_entry, enqueue_after_commit=True)\n",[42,1361,1362,1366,1370,1374,1379,1384,1389,1394,1399],{"__ignoreMap":275},[279,1363,1364],{"class":281,"line":282},[279,1365,789],{},[279,1367,1368],{"class":281,"line":288},[279,1369,800],{"emptyLinePlaceholder":799},[279,1371,1372],{"class":281,"line":294},[279,1373,800],{"emptyLinePlaceholder":799},[279,1375,1376],{"class":281,"line":300},[279,1377,1378],{},"def marquer_paye(bank_transaction, row):\n",[279,1380,1381],{"class":281,"line":682},[279,1382,1383],{},"    if row.payment_document != \"Loan Repayment\":\n",[279,1385,1386],{"class":281,"line":688},[279,1387,1388],{},"        return\n",[279,1390,1391],{"class":281,"line":694},[279,1392,1393],{},"    frappe.get_doc(\"Loan Repayment\", row.payment_entry).set_status(update=True)\n",[279,1395,1396],{"class":281,"line":700},[279,1397,1398],{},"    # Appel externe : seulement après la validation de la transaction\n",[279,1400,1401],{"class":281,"line":706},[279,1402,1403],{},"    frappe.enqueue(\"mon_app.notifications.preteur\", remboursement=row.payment_entry, enqueue_after_commit=True)\n",[19,1405,1086,1406,1409,1410,1413,1414,1417,1418,314,1421,314,1424,314,1427,1430],{},[42,1407,1408],{},"fn(bank_transaction, row) -> None",". ",[42,1411,1412],{},"row"," est la ligne de la table ",[170,1415,1416],{},"Paiements"," de la transaction : ",[42,1419,1420],{},"payment_document",[42,1422,1423],{},"payment_entry",[42,1425,1426],{},"allocated_amount",[42,1428,1429],{},"reconciliation_type"," (« Matched » ou « Voucher Created » si le rapprochement a créé le document).",[14,1432,1435],{"color":1433,"icon":1434},"red","i-mdi-alert",[19,1436,1437,1438,1441,1442,1445,1446,1449],{},"Les événements tournent ",[170,1439,1440],{},"dans la même transaction de base de données"," que le rapprochement. Une exception dans votre fonction ",[170,1443,1444],{},"bloque le rapprochement"," : tout est annulé et l'utilisateur voit votre message d'erreur. N'appelez jamais un service externe (HTTP, e-mail, autre site) directement : utilisez ",[42,1447,1448],{},"frappe.enqueue(..., enqueue_after_commit=True)",", pour que rien ne parte si le rapprochement est annulé.",[199,1451,1453,1455],{"id":1452},"bank_reconciliation_actions-ajouter-une-action",[42,1454,163],{}," : ajouter une action",[19,1457,1458,1459,1461,1462,1465,1466,1469],{},"Une action s'affiche sous le bouton ",[170,1460,172],{},". Les rapprochements depuis un ",[170,1463,1464],{},"Ordre de paiement"," et depuis un ",[170,1467,1468],{},"Prélèvement SEPA"," utilisent ce même mécanisme.",[270,1471,1473],{"className":272,"code":1472,"language":274,"meta":275,"style":275},"# mon_app\u002Fhooks.py\nbank_reconciliation_actions = [\"mon_app.rapprochement.action_remboursement\"]\n",[42,1474,1475,1479],{"__ignoreMap":275},[279,1476,1477],{"class":281,"line":282},[279,1478,285],{},[279,1480,1481],{"class":281,"line":288},[279,1482,1483],{},"bank_reconciliation_actions = [\"mon_app.rapprochement.action_remboursement\"]\n",[19,1485,1486,1487,1489],{},"La fonction déclarée renvoie la description de l'action, ou ",[42,1488,617],{}," pour la masquer :",[270,1491,1493],{"className":272,"code":1492,"language":274,"meta":275,"style":275},"import frappe\nfrom frappe import _\n\n\ndef action_remboursement(context):\n    if not frappe.has_permission(\"Loan Repayment\", \"write\"):\n        return None  # l'utilisateur n'a pas le droit : action masquée\n    return {\n        \"name\": \"loan_repayment\",\n        \"label\": _(\"Rapprocher avec un remboursement de prêt\"),\n        \"method\": \"mon_app.rapprochement.rapprocher_remboursement\",\n        \"when\": {\"min_transactions\": 1, \"max_transactions\": 1, \"direction\": \"out\", \"needs_documents\": False},\n        \"input\": {\n            \"fieldtype\": \"Link\",\n            \"options\": \"Loan Repayment\",\n            \"filters\": {\"docstatus\": 1},\n            \"prefill_method\": \"mon_app.rapprochement.deviner_remboursement\",\n        },\n        \"confirm\": _(\"Une écriture de journal sera créée. Continuer ?\"),\n        \"sort_order\": 50,\n    }\n\n\n@frappe.whitelist(methods=[\"POST\"])\ndef rapprocher_remboursement(bank_transactions, documents, value=None):\n    frappe.has_permission(\"Loan Repayment\", \"write\", throw=True)\n    # ... rapprochement ...\n    return {\"reconciled\": 1, \"message\": None, \"open\": None}\n",[42,1494,1495,1499,1503,1507,1511,1516,1521,1526,1531,1536,1541,1546,1551,1556,1561,1566,1571,1576,1581,1586,1591,1596,1600,1604,1609,1614,1619,1624],{"__ignoreMap":275},[279,1496,1497],{"class":281,"line":282},[279,1498,789],{},[279,1500,1501],{"class":281,"line":288},[279,1502,1277],{},[279,1504,1505],{"class":281,"line":294},[279,1506,800],{"emptyLinePlaceholder":799},[279,1508,1509],{"class":281,"line":300},[279,1510,800],{"emptyLinePlaceholder":799},[279,1512,1513],{"class":281,"line":682},[279,1514,1515],{},"def action_remboursement(context):\n",[279,1517,1518],{"class":281,"line":688},[279,1519,1520],{},"    if not frappe.has_permission(\"Loan Repayment\", \"write\"):\n",[279,1522,1523],{"class":281,"line":694},[279,1524,1525],{},"        return None  # l'utilisateur n'a pas le droit : action masquée\n",[279,1527,1528],{"class":281,"line":700},[279,1529,1530],{},"    return {\n",[279,1532,1533],{"class":281,"line":706},[279,1534,1535],{},"        \"name\": \"loan_repayment\",\n",[279,1537,1538],{"class":281,"line":712},[279,1539,1540],{},"        \"label\": _(\"Rapprocher avec un remboursement de prêt\"),\n",[279,1542,1543],{"class":281,"line":718},[279,1544,1545],{},"        \"method\": \"mon_app.rapprochement.rapprocher_remboursement\",\n",[279,1547,1548],{"class":281,"line":724},[279,1549,1550],{},"        \"when\": {\"min_transactions\": 1, \"max_transactions\": 1, \"direction\": \"out\", \"needs_documents\": False},\n",[279,1552,1553],{"class":281,"line":730},[279,1554,1555],{},"        \"input\": {\n",[279,1557,1558],{"class":281,"line":736},[279,1559,1560],{},"            \"fieldtype\": \"Link\",\n",[279,1562,1563],{"class":281,"line":742},[279,1564,1565],{},"            \"options\": \"Loan Repayment\",\n",[279,1567,1568],{"class":281,"line":748},[279,1569,1570],{},"            \"filters\": {\"docstatus\": 1},\n",[279,1572,1573],{"class":281,"line":754},[279,1574,1575],{},"            \"prefill_method\": \"mon_app.rapprochement.deviner_remboursement\",\n",[279,1577,1578],{"class":281,"line":866},[279,1579,1580],{},"        },\n",[279,1582,1583],{"class":281,"line":872},[279,1584,1585],{},"        \"confirm\": _(\"Une écriture de journal sera créée. Continuer ?\"),\n",[279,1587,1588],{"class":281,"line":878},[279,1589,1590],{},"        \"sort_order\": 50,\n",[279,1592,1593],{"class":281,"line":884},[279,1594,1595],{},"    }\n",[279,1597,1598],{"class":281,"line":890},[279,1599,800],{"emptyLinePlaceholder":799},[279,1601,1602],{"class":281,"line":896},[279,1603,800],{"emptyLinePlaceholder":799},[279,1605,1606],{"class":281,"line":902},[279,1607,1608],{},"@frappe.whitelist(methods=[\"POST\"])\n",[279,1610,1611],{"class":281,"line":908},[279,1612,1613],{},"def rapprocher_remboursement(bank_transactions, documents, value=None):\n",[279,1615,1616],{"class":281,"line":914},[279,1617,1618],{},"    frappe.has_permission(\"Loan Repayment\", \"write\", throw=True)\n",[279,1620,1621],{"class":281,"line":920},[279,1622,1623],{},"    # ... rapprochement ...\n",[279,1625,1626],{"class":281,"line":926},[279,1627,1628],{},"    return {\"reconciled\": 1, \"message\": None, \"open\": None}\n",[55,1630,1631,1640],{},[58,1632,1633],{},[61,1634,1635,1638],{},[64,1636,1637],{},"Clé",[64,1639,72],{},[74,1641,1642,1654,1677,1697,1711],{},[61,1643,1644,1651],{},[79,1645,1646,314,1649],{},[42,1647,1648],{},"name",[42,1650,371],{},[79,1652,1653],{},"Identifiant unique, libellé du bouton",[61,1655,1656,1661],{},[79,1657,1658],{},[42,1659,1660],{},"method",[79,1662,1663,1664,1667,1668,314,1670,318,1673,1676],{},"Méthode ",[42,1665,1666],{},"@frappe.whitelist"," appelée avec ",[42,1669,628],{},[42,1671,1672],{},"documents",[42,1674,1675],{},"value"," (valeur du champ)",[61,1678,1679,1684],{},[79,1680,1681],{},[42,1682,1683],{},"when",[79,1685,1686,1687,314,1690,314,1693,1696],{},"Conditions d'affichage : nombre de transactions, sens (",[42,1688,1689],{},"in",[42,1691,1692],{},"out",[42,1694,1695],{},"any","), documents requis",[61,1698,1699,1704],{},[79,1700,1701],{},[42,1702,1703],{},"input",[79,1705,1706,1707,1710],{},"Champ Lien facultatif avant le bouton ; ",[42,1708,1709],{},"prefill_method(bank_transaction) -> str | None"," le pré-remplit",[61,1712,1713,1718],{},[79,1714,1715],{},[42,1716,1717],{},"confirm",[79,1719,1720],{},"Message de confirmation facultatif",[19,1722,1723,1724,53],{},"La méthode renvoie ",[42,1725,1726],{},"{\"reconciled\": int, \"message\": str | None, \"open\": {\"doctype\": ..., \"name\": ...} | None}",[19,1728,1729,1732,1733,1736,1737,1739],{},[170,1730,1731],{},"Permissions"," : Dokos ne gère pas de liste de rôles pour les actions. Votre méthode ",[170,1734,1735],{},"doit vérifier elle-même"," les permissions. Masquer l'action (renvoyer ",[42,1738,617],{},") évite seulement de la montrer à un utilisateur qui ne peut pas l'utiliser.",[199,1741,1743,1745],{"id":1742},"bank_reconciliation_transaction_columns-colonnes-de-transactions",[42,1744,179],{}," : colonnes de transactions",[270,1747,1749],{"className":272,"code":1748,"language":274,"meta":275,"style":275},"# mon_app\u002Fhooks.py\nbank_reconciliation_transaction_columns = [\"mon_app.rapprochement.colonnes\"]\n",[42,1750,1751,1755],{"__ignoreMap":275},[279,1752,1753],{"class":281,"line":282},[279,1754,285],{},[279,1756,1757],{"class":281,"line":288},[279,1758,1759],{},"bank_reconciliation_transaction_columns = [\"mon_app.rapprochement.colonnes\"]\n",[270,1761,1763],{"className":272,"code":1762,"language":274,"meta":275,"style":275},"def colonnes():\n    # custom_categorie_banque : champ personnalisé de la Transaction bancaire\n    return [{\"field\": \"custom_categorie_banque\", \"label\": \"Catégorie de la banque\", \"format\": \"Data\"}]\n",[42,1764,1765,1770,1775],{"__ignoreMap":275},[279,1766,1767],{"class":281,"line":282},[279,1768,1769],{},"def colonnes():\n",[279,1771,1772],{"class":281,"line":288},[279,1773,1774],{},"    # custom_categorie_banque : champ personnalisé de la Transaction bancaire\n",[279,1776,1777],{"class":281,"line":294},[279,1778,1779],{},"    return [{\"field\": \"custom_categorie_banque\", \"label\": \"Catégorie de la banque\", \"format\": \"Data\"}]\n",[19,1781,1086,1782,1785,1786,314,1789,1791,1792,213,1795,314,1798,314,1801,314,1804,1807,1808,314,1811,314,1814,1817,1818,1820,1821,1823,1824,1827,1828,53],{},[42,1783,1784],{},"fn() -> list[dict]",". Chaque colonne a ",[42,1787,1788],{},"field",[42,1790,371],{}," et facultativement ",[42,1793,1794],{},"format",[42,1796,1797],{},"Currency",[42,1799,1800],{},"Date",[42,1802,1803],{},"Data",[42,1805,1806],{},"Link","), ",[42,1809,1810],{},"align",[42,1812,1813],{},"hidden",[42,1815,1816],{},"sortable",". Le champ doit exister sur la ",[170,1819,258],{}," (champ standard ou personnalisé) ; Dokos refuse les autres. Les colonnes du tableau des documents se déclarent dans l'attribut ",[42,1822,480],{}," du fournisseur, avec ",[42,1825,1826],{},"extra.\u003Cclé>"," pour lire les données de ",[42,1829,1830],{},"extra",[199,1832,1834,1836],{"id":1833},"bank_reconciliation_js-panneaux-javascript",[42,1835,191],{}," : panneaux JavaScript",[19,1838,1839,1840,1843],{},"Pour afficher un bandeau, un panneau ou un badge, déclarez un bundle JavaScript de l'application. La page le charge ",[170,1841,1842],{},"avant"," d'afficher son interface.",[270,1845,1847],{"className":272,"code":1846,"language":274,"meta":275,"style":275},"# mon_app\u002Fhooks.py\nbank_reconciliation_js = [\"mon_app_rapprochement.bundle.js\"]\n",[42,1848,1849,1853],{"__ignoreMap":275},[279,1850,1851],{"class":281,"line":282},[279,1852,285],{},[279,1854,1855],{"class":281,"line":288},[279,1856,1857],{},"bank_reconciliation_js = [\"mon_app_rapprochement.bundle.js\"]\n",[19,1859,1860,1861,1864],{},"Le bundle inscrit une extension dans le registre ",[42,1862,1863],{},"erpnext.bank_reconciliation.extensions"," :",[270,1866,1870],{"className":1867,"code":1868,"language":1869,"meta":275,"style":275},"language-js shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","\u002F\u002F mon_app\u002Fpublic\u002Fjs\u002Fmon_app_rapprochement.bundle.js\nerpnext.bank_reconciliation.extensions.register({\n    name: \"mon_app.aide_contrat\",\n    sort_order: 50,\n    slots: {\n        \"documents.footer\": (el, ctx) => {\n            const render = (c) => {\n                el.textContent =\n                    c.document_type === \"Loan Repayment\"\n                        ? __(\"Le numéro de contrat dans le libellé sélectionne le remboursement.\")\n                        : \"\";\n            };\n            render(ctx);\n            return { update: render };\n        },\n    },\n    format_candidate(row) {\n        if (row.doctype === \"Loan Repayment\" && row.score >= 95) row.party_name += \" ★\";\n        return row;\n    },\n});\n","js",[42,1871,1872,1878,1906,1928,1941,1951,1984,2006,2019,2039,2059,2070,2075,2089,2108,2112,2117,2130,2190,2199,2203],{"__ignoreMap":275},[279,1873,1874],{"class":281,"line":282},[279,1875,1877],{"class":1876},"sHwdD","\u002F\u002F mon_app\u002Fpublic\u002Fjs\u002Fmon_app_rapprochement.bundle.js\n",[279,1879,1880,1884,1887,1890,1892,1895,1897,1901,1904],{"class":281,"line":288},[279,1881,1883],{"class":1882},"sTEyZ","erpnext",[279,1885,53],{"class":1886},"sMK4o",[279,1888,1889],{"class":1882},"bank_reconciliation",[279,1891,53],{"class":1886},[279,1893,1894],{"class":1882},"extensions",[279,1896,53],{"class":1886},[279,1898,1900],{"class":1899},"s2Zo4","register",[279,1902,1903],{"class":1882},"(",[279,1905,664],{"class":1886},[279,1907,1908,1912,1915,1918,1922,1925],{"class":281,"line":294},[279,1909,1911],{"class":1910},"swJcz","    name",[279,1913,1914],{"class":1886},":",[279,1916,1917],{"class":1886}," \"",[279,1919,1921],{"class":1920},"sfazB","mon_app.aide_contrat",[279,1923,1924],{"class":1886},"\"",[279,1926,1927],{"class":1886},",\n",[279,1929,1930,1933,1935,1939],{"class":281,"line":300},[279,1931,1932],{"class":1910},"    sort_order",[279,1934,1914],{"class":1886},[279,1936,1938],{"class":1937},"sbssI"," 50",[279,1940,1927],{"class":1886},[279,1942,1943,1946,1948],{"class":281,"line":682},[279,1944,1945],{"class":1910},"    slots",[279,1947,1914],{"class":1886},[279,1949,1950],{"class":1886}," {\n",[279,1952,1953,1956,1959,1961,1963,1965,1969,1972,1975,1978,1982],{"class":281,"line":688},[279,1954,1955],{"class":1886},"        \"",[279,1957,1958],{"class":1910},"documents.footer",[279,1960,1924],{"class":1886},[279,1962,1914],{"class":1886},[279,1964,213],{"class":1886},[279,1966,1968],{"class":1967},"sHdIc","el",[279,1970,1971],{"class":1886},",",[279,1973,1974],{"class":1967}," ctx",[279,1976,1977],{"class":1886},")",[279,1979,1981],{"class":1980},"spNyl"," =>",[279,1983,1950],{"class":1886},[279,1985,1986,1989,1992,1995,1997,2000,2002,2004],{"class":281,"line":694},[279,1987,1988],{"class":1980},"            const",[279,1990,1991],{"class":1882}," render",[279,1993,1994],{"class":1886}," =",[279,1996,213],{"class":1886},[279,1998,1999],{"class":1967},"c",[279,2001,1977],{"class":1886},[279,2003,1981],{"class":1980},[279,2005,1950],{"class":1886},[279,2007,2008,2011,2013,2016],{"class":281,"line":700},[279,2009,2010],{"class":1882},"                el",[279,2012,53],{"class":1886},[279,2014,2015],{"class":1882},"textContent",[279,2017,2018],{"class":1886}," =\n",[279,2020,2021,2024,2026,2029,2032,2034,2036],{"class":281,"line":706},[279,2022,2023],{"class":1882},"                    c",[279,2025,53],{"class":1886},[279,2027,2028],{"class":1882},"document_type",[279,2030,2031],{"class":1886}," ===",[279,2033,1917],{"class":1886},[279,2035,1019],{"class":1920},[279,2037,2038],{"class":1886},"\"\n",[279,2040,2041,2044,2047,2049,2051,2054,2056],{"class":281,"line":712},[279,2042,2043],{"class":1886},"                        ?",[279,2045,2046],{"class":1899}," __",[279,2048,1903],{"class":1910},[279,2050,1924],{"class":1886},[279,2052,2053],{"class":1920},"Le numéro de contrat dans le libellé sélectionne le remboursement.",[279,2055,1924],{"class":1886},[279,2057,2058],{"class":1910},")\n",[279,2060,2061,2064,2067],{"class":281,"line":718},[279,2062,2063],{"class":1886},"                        :",[279,2065,2066],{"class":1886}," \"\"",[279,2068,2069],{"class":1886},";\n",[279,2071,2072],{"class":281,"line":724},[279,2073,2074],{"class":1886},"            };\n",[279,2076,2077,2080,2082,2085,2087],{"class":281,"line":730},[279,2078,2079],{"class":1899},"            render",[279,2081,1903],{"class":1910},[279,2083,2084],{"class":1882},"ctx",[279,2086,1977],{"class":1910},[279,2088,2069],{"class":1886},[279,2090,2091,2095,2098,2101,2103,2105],{"class":281,"line":736},[279,2092,2094],{"class":2093},"s7zQu","            return",[279,2096,2097],{"class":1886}," {",[279,2099,2100],{"class":1910}," update",[279,2102,1914],{"class":1886},[279,2104,1991],{"class":1882},[279,2106,2107],{"class":1886}," };\n",[279,2109,2110],{"class":281,"line":742},[279,2111,1580],{"class":1886},[279,2113,2114],{"class":281,"line":748},[279,2115,2116],{"class":1886},"    },\n",[279,2118,2119,2122,2124,2126,2128],{"class":281,"line":754},[279,2120,2121],{"class":1910},"    format_candidate",[279,2123,1903],{"class":1886},[279,2125,1412],{"class":1967},[279,2127,1977],{"class":1886},[279,2129,1950],{"class":1886},[279,2131,2132,2135,2137,2139,2141,2143,2145,2147,2149,2151,2154,2157,2159,2162,2165,2168,2171,2173,2175,2178,2181,2183,2186,2188],{"class":281,"line":866},[279,2133,2134],{"class":2093},"        if",[279,2136,213],{"class":1910},[279,2138,1412],{"class":1882},[279,2140,53],{"class":1886},[279,2142,356],{"class":1882},[279,2144,2031],{"class":1886},[279,2146,1917],{"class":1886},[279,2148,1019],{"class":1920},[279,2150,1924],{"class":1886},[279,2152,2153],{"class":1886}," &&",[279,2155,2156],{"class":1882}," row",[279,2158,53],{"class":1886},[279,2160,2161],{"class":1882},"score",[279,2163,2164],{"class":1886}," >=",[279,2166,2167],{"class":1937}," 95",[279,2169,2170],{"class":1910},") ",[279,2172,1412],{"class":1882},[279,2174,53],{"class":1886},[279,2176,2177],{"class":1882},"party_name",[279,2179,2180],{"class":1886}," +=",[279,2182,1917],{"class":1886},[279,2184,2185],{"class":1920}," ★",[279,2187,1924],{"class":1886},[279,2189,2069],{"class":1886},[279,2191,2192,2195,2197],{"class":281,"line":872},[279,2193,2194],{"class":2093},"        return",[279,2196,2156],{"class":1882},[279,2198,2069],{"class":1886},[279,2200,2201],{"class":281,"line":878},[279,2202,2116],{"class":1886},[279,2204,2205,2208,2210],{"class":281,"line":884},[279,2206,2207],{"class":1886},"}",[279,2209,1977],{"class":1882},[279,2211,2069],{"class":1886},[55,2213,2214,2224],{},[58,2215,2216],{},[61,2217,2218,2221],{},[64,2219,2220],{},"Emplacement",[64,2222,2223],{},"Position",[74,2225,2226,2236,2246,2255],{},[61,2227,2228,2233],{},[79,2229,2230],{},[42,2231,2232],{},"page.header",[79,2234,2235],{},"Au-dessus des indicateurs de la page",[61,2237,2238,2243],{},[79,2239,2240],{},[42,2241,2242],{},"transactions.toolbar",[79,2244,2245],{},"Barre d'outils de la liste des transactions",[61,2247,2248,2252],{},[79,2249,2250],{},[42,2251,1958],{},[79,2253,2254],{},"Sous le tableau des documents",[61,2256,2257,2262],{},[79,2258,2259],{},[42,2260,2261],{},"actions.extra",[79,2263,2264,2265],{},"Sous le bouton ",[170,2266,172],{},[19,2268,2269,2270,2272,2273,1409,2276,2278,2279,318,2282,53],{},"Une fonction d'emplacement reçoit l'élément HTML et le contexte ",[42,2271,2084],{},", et peut renvoyer ",[42,2274,2275],{},"{ update(ctx), destroy() }",[42,2277,2084],{}," contient le compte bancaire, la société, la devise, la période, les transactions et documents sélectionnés, l'onglet courant, la configuration, et deux fonctions : ",[42,2280,2281],{},"refresh()",[42,2283,2284],{},"reconcile(documents)",[19,2286,2287,2288,2291,2292,767,2295,2298,2299,2301],{},"Les autres fonctions facultatives : ",[42,2289,2290],{},"format_candidate(row, ctx)"," modifie l'affichage d'un document ; ",[42,2293,2294],{},"can_reconcile(ctx)",[42,2296,2297],{},"true"," ou un texte qui désactive ",[170,2300,172],{}," et explique pourquoi.",[19,2303,2304,2305,318,2308,2311,2312,2315,2316,318,2319,2322],{},"La page émet aussi les événements ",[42,2306,2307],{},"reconciled",[42,2309,2310],{},"selection_change"," sur ",[42,2313,2314],{},"erpnext.bank_reconciliation"," (en plus de ",[42,2317,2318],{},"filter_change",[42,2320,2321],{},"refresh",") :",[270,2324,2326],{"className":1867,"code":2325,"language":1869,"meta":275,"style":275},"erpnext.bank_reconciliation.on(\"reconciled\", ({ bank_transactions, documents, result }) => { ... });\n",[42,2327,2328],{"__ignoreMap":275},[279,2329,2330,2332,2334,2336,2338,2341,2343,2345,2347,2349,2351,2354,2357,2359,2362,2364,2367,2370,2372,2374,2377,2380,2382],{"class":281,"line":282},[279,2331,1883],{"class":1882},[279,2333,53],{"class":1886},[279,2335,1889],{"class":1882},[279,2337,53],{"class":1886},[279,2339,2340],{"class":1899},"on",[279,2342,1903],{"class":1882},[279,2344,1924],{"class":1886},[279,2346,2307],{"class":1920},[279,2348,1924],{"class":1886},[279,2350,1971],{"class":1886},[279,2352,2353],{"class":1886}," ({",[279,2355,2356],{"class":1967}," bank_transactions",[279,2358,1971],{"class":1886},[279,2360,2361],{"class":1967}," documents",[279,2363,1971],{"class":1886},[279,2365,2366],{"class":1967}," result",[279,2368,2369],{"class":1886}," })",[279,2371,1981],{"class":1980},[279,2373,2097],{"class":1886},[279,2375,2376],{"class":1886}," ...",[279,2378,2379],{"class":1886}," }",[279,2381,1977],{"class":1882},[279,2383,2069],{"class":1886},[14,2385,2388],{"color":2386,"icon":2387},"blue","i-mdi-information",[19,2389,2390,2391,2394,2395,2398],{},"Les emplacements attendent une fonction, pas un composant Vue : chaque bundle embarque sa propre copie de Vue. Pour utiliser Vue, montez votre propre application dans la fonction (",[42,2392,2393],{},"createApp(MonPanneau, { ctx }).mount(el)",") et démontez-la dans ",[42,2396,2397],{},"destroy()",". Une erreur dans une extension est interceptée et écrite dans la console du navigateur : la page et les autres extensions continuent de fonctionner.",[199,2400,2402],{"id":2401},"points-dattention","Points d'attention",[204,2404,2405,2408,2416,2419,2422],{},[207,2406,2407],{},"Les erreurs des fournisseurs, règles et validateurs ne sont pas interceptées : elles arrêtent l'opération en cours et l'utilisateur voit le message.",[207,2409,2410,2411,318,2413,2415],{},"Les événements ",[42,2412,250],{},[42,2414,254],{}," bloquent le rapprochement en cas d'erreur (voir plus haut).",[207,2417,2418],{},"En rapprochement automatique, une erreur annule seulement la transaction concernée.",[207,2420,2421],{},"Gardez les règles de score sans effet de bord : elles sont appelées à chaque changement de sélection.",[207,2423,2424,314,2426,318,2429,2432],{},[42,2425,1019],{},[42,2427,2428],{},"contract_number",[42,2430,2431],{},"custom_categorie_banque"," sont des exemples fictifs, à créer dans votre application.",[2434,2435,2436],"style",{},"html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}html pre.shiki code .sHdIc, html code.shiki .sHdIc{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#EEFFFF;--shiki-default-font-style:italic;--shiki-dark:#BABED8;--shiki-dark-font-style:italic}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .s7zQu, html code.shiki .s7zQu{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}",{"title":275,"searchDepth":282,"depth":288,"links":2438},[2439,2440,2446,2448,2450,2452,2454,2456,2458,2460,2462],{"id":201,"depth":288,"text":202},{"id":262,"depth":288,"text":2441,"children":2442},"bank_reconciliation_providers : ajouter un type de document",[2443,2444,2445],{"id":325,"depth":294,"text":326},{"id":647,"depth":294,"text":648},{"id":773,"depth":294,"text":774},{"id":1023,"depth":288,"text":2447},"bank_reconciliation_match_rules : classer les documents proposés",{"id":1136,"depth":288,"text":2449},"auto_reconciliation_methods : rapprochement automatique",{"id":1207,"depth":288,"text":2451},"bank_reconciliation_batch_reconcilers : virements groupés",{"id":1240,"depth":288,"text":2453},"bank_reconciliation_validators : refuser un rapprochement",{"id":1313,"depth":288,"text":2455},"bank_reconciliation_events : réagir à un rapprochement",{"id":1452,"depth":288,"text":2457},"bank_reconciliation_actions : ajouter une action",{"id":1742,"depth":288,"text":2459},"bank_reconciliation_transaction_columns : colonnes de transactions",{"id":1833,"depth":288,"text":2461},"bank_reconciliation_js : panneaux JavaScript",{"id":2401,"depth":288,"text":2402},"Étendre la page Rapprochement bancaire depuis une application : types de documents, règles de score, rapprochement automatique, validations, événements, actions, colonnes et panneaux JavaScript.","md",{"generated":799,"reviewed":2466,"source_mrs":2467},false,[],"\u002Fnext\u002Fdodock\u002Fdeveloppeurs\u002Fhooks-rapprochement-bancaire",{"title":5,"description":2463},"2.next\u002F3.dodock\u002F10.developpeurs\u002Fhooks-rapprochement-bancaire","aLMpS7CnTkeGM05qQlDYv9u2mYYxdPGCtEjJXyDW09c",{},1794695078784]