1. Le document papier a été scanné vers un répertoire d'Alfresco. (le document est scanné avec d'autres documents. Chaque première page possède un code-barre autocollant (sera utile pour découpé le PDF en plusieurs PDF).
2. Une règle découpe le PDF en plusieurs PDF et chaque nouveau document devient un type définit par un modèle de document (ici le type Facture). Les nouvelles métadonnées (comme le numéro de la facture) sont à 0.
3. Via une application tierce utilisant un webscript les métadonnées sont définies et ajoute aussi l'aspect (doMove). L'ajout de cet aspect déclenche une règle qui va déplacer le document dans un dossier.
4. L'application tierce pourra afficher le nouveau document via un webscript (en passant le numéro de la facture).
Ce processus est utilisé depuis plusieurs mois avec beaucoup de documents. Il n'a jamais été constaté un problème pour retrouver un document.Vous parlez de recherches, sont-elles faites depuis l'interface Share (ou Explorer) ou via des développements spécifiquesLa recherche est effectuée depuis Explorer. Elle marche pour la plupart des documents.
<?xml version="1.0" encoding="UTF-8"?>
<model name="sg:customGeneral" xmlns="http://www.alfresco.org/model/dictionary/1.0">
<description>General</description>
<author></author>
<version>1.0</version>
<imports>
<import uri="http://www.alfresco.org/model/dictionary/1.0"
prefix="d" />
<import uri="http://www.alfresco.org/model/content/1.0" prefix="cm" />
</imports>
<namespaces>
<namespace uri="http://www.custom.ch/model/general/1.0"
prefix="sg" />
</namespaces>
<constraints>
<constraint name="sg:int_positive_Constraint" type="REGEX">
<parameter name="expression">
<value>\d*</value>
</parameter>
<parameter name="requiresMatch">
<value>true</value>
</parameter>
</constraint>
<constraint name="sg:money" type="REGEX">
<parameter name="expression">
<value>\d+\.\d{0,2}</value>
</parameter>
<parameter name="requiresMatch">
<value>true</value>
</parameter>
</constraint>
<!– <constraint name="sg:SingleDoc" type="ch.custom.manageoffice.model.constraint.SingleDocConstraint">
</constraint> –>
</constraints>
<!– ****************************** –>
<!– Types –>
<!– ****************************** –>
<types>
<!– Enterprise-wide generic document type –>
<type name="sg:doc">
<title>Document</title>
<parent>cm:content</parent>
<properties>
<!– Document id –>
<property name="sg:documentNb">
<type>d:int</type>
<constraints>
<constraint ref="sg:int_positive_Constraint" />
</constraints>
</property>
<!– Nb Firm (fpa_no) –>
<property name="sg:firmNb">
<type>d:int</type>
<constraints>
<constraint ref="sg:int_positive_Constraint" />
</constraints>
</property>
</properties>
<associations>
<association name="sg:relatedDocuments">
<title>Related Documents</title>
<source>
<mandatory>false</mandatory>
<many>true</many>
</source>
<target>
<class>cm:content</class>
<mandatory>false</mandatory>
<many>true</many>
</target>
</association>
</associations>
<mandatory-aspects>
<aspect>cm:generalclassifiable</aspect>
</mandatory-aspects>
</type>
</types>
<!– ****************************** –>
<!– Aspects –>
<!– ****************************** –>
<aspects>
<aspect name="sg:treatable">
<title>To treat by the ERP</title>
<properties>
<property name="sg:toTreated">
<title>Must be treated by the ERP</title>
<type>d:boolean</type>
<default>true</default>
</property>
<property name="sg:responsible">
<title>People responsible of the document</title>
<type>d:text</type>
</property>
</properties>
</aspect>
<!– Deletable –>
<!– Will be moved in the special space –>
<aspect name="sg:deletable">
<title>To treat by the ERP</title>
<properties>
<property name="sg:toDelete">
<title>Must be deleted</title>
<type>d:boolean</type>
<default>true</default>
</property>
</properties>
</aspect>
<!– Move –>
<aspect name="sg:displaceable">
<title>The document can move (go in other directory)</title>
<properties>
<property name="sg:toDisplace">
<title>Must move</title>
<type>d:boolean</type>
<default>true</default>
</property>
</properties>
</aspect>
<!– Annexe –>
<aspect name="sg:annexe">
<title>The document can move (go in other directory)</title>
<properties>
<property name="sg:isAnnexe">
<title>Is an annexe</title>
<type>d:boolean</type>
<default>true</default>
</property>
</properties>
</aspect>
<!– Customer –>
<aspect name="sg:customer">
<title>Related to a customer</title>
<properties>
<property name="sg:customerNb">
<type>d:int</type>
<constraints>
<constraint ref="sg:int_positive_Constraint" />
</constraints>
</property>
</properties>
</aspect>
<!– Distributor –>
<aspect name="sg:distributor">
<title>Related to a distributor</title>
<properties>
<!– Distributor id –>
<property name="sg:distributorNb">
<type>d:int</type>
<constraints>
<constraint ref="sg:int_positive_Constraint" />
</constraints>
</property>
</properties>
</aspect>
<!– Collaborator –>
<aspect name="sg:collaborator">
<title>Related to a collaborator</title>
<properties>
<!– Collaborator id –>
<property name="sg:collaboratorNb">
<type>d:int</type>
<constraints>
<constraint ref="sg:int_positive_Constraint" />
</constraints>
</property>
</properties>
</aspect>
<!– Student –>
<aspect name="sg:student">
<title>Related to a student</title>
<properties>
<!– Student id –>
<property name="sg:studentNb">
<type>d:int</type>
<constraints>
<constraint ref="sg:int_positive_Constraint" />
</constraints>
</property>
</properties>
</aspect>
<!– List –>
<aspect name="sg:list">
<title>Related to a list</title>
<properties>
<property name="sg:listAny">
<type>d:any</type>
</property>
</properties>
</aspect>
</aspects>
</model>
Modèle spécifique
<?xml version="1.0" encoding="UTF-8"?>
<model name="sgf:customFinance" xmlns="http://www.alfresco.org/model/dictionary/1.0">
<description>Model for documents</description>
<author></author>
<version>1.0</version>
<imports>
<import uri="http://www.alfresco.org/model/dictionary/1.0"
prefix="d" />
<import uri="http://www.alfresco.org/model/content/1.0" prefix="cm" />
<import uri="http://www.custom.ch/model/general/1.0" prefix="sg" />
</imports>
<namespaces>
<namespace uri="http://www.custom.ch/model/finance/1.0"
prefix="sgf" />
</namespaces>
<types>
<!– ******** –>
<!– Invoices –>
<!– ******** –>
<type name="sgf:invoice">
<title>Invoice</title>
<parent>sg:doc</parent>
<properties>
<!– BVR (ecr_bvr) –>
<property name="sgf:bvr">
<type>d:text</type>
</property>
</properties>
</type>
<!– Creditor invoice(enter in the ERP) type 30 –>
<type name="sgf:invoiceCreditor">
<title>Creditor invoice</title>
<parent>sgf:invoice</parent>
<!– Nb Distributor –>
<mandatory-aspects>
<aspect>sg:distributor</aspect>
</mandatory-aspects>
</type>
<!– Debtor invoice (go away from ERP) type 20–>
<type name="sgf:invoiceDebtor">
<title>Debtor Invoice</title>
<parent>sgf:invoice</parent>
<!– Nb Customer –>
<mandatory-aspects>
<aspect>sg:customer</aspect>
</mandatory-aspects>
</type>
<!– ******* –>
<!– Payment –>
<!– ******* –>
<type name="sgf:payment">
<title>Payment</title>
<parent>sg:doc</parent>
</type>
<!– Creditor Payment (enter in the ERP) type 31 –>
<type name="sgf:paymentCreditor">
<title>Creditor Payment</title>
<parent>sgf:payment</parent>
<!– Nb Distributor –>
<mandatory-aspects>
<aspect>sg:distributor</aspect>
</mandatory-aspects>
</type>
<!– Debtor Payment (go away from ERP) type 21–>
<type name="sgf:paymentDebtor">
<title>Debtor Payment</title>
<parent>sgf:payment</parent>
<!– Nb Customer –>
<mandatory-aspects>
<aspect>sg:customer</aspect>
</mandatory-aspects>
</type>
<!– ******************************************* –>
<!– Financial or/and analytical account type 10 –>
<!– ******************************************* –>
<type name="sgf:financialAccount">
<title>Financial/analytical account</title>
<parent>sg:doc</parent>
</type>
<!– ************************* –>
<!– Condensed account type 50 –>
<!– ************************* –>
<type name="sgf:condensedAccount">
<title>Condensed account</title>
<parent>sg:doc</parent>
</type>
<!– ******* –>
<!– Salary –>
<!– ******* –>
<type name="sgf:salary">
<title>Salary sheet</title>
<parent>sg:doc</parent>
<properties>
<property name="sgf:dateSalary">
<title>Date of the salary sheet</title>
<type>d:date</type>
</property>
<!– Amount –>
<property name="sgf:salaryAmount">
<type>d:float</type>
<constraints>
<constraint ref="sg:money" />
</constraints>
</property>
</properties>
<!– Nb Collaborator –>
<mandatory-aspects>
<aspect>sg:collaborator</aspect>
</mandatory-aspects>
</type>
</types>
</model>
// *****************
// Arguments comming
// *****************
var nodeReference = args.nodeReference;
var fileName = args.fileName;
var firmNb = args.firmNb;
var documentNb = args.documentNb;
var bvr = args.bvr;
var relatedTo = args.relatedTo;
var toTreated = args.toTreated;
var responsible = args.responsible;
var toMove = args.toMove;
var toDelete = args.toDelete;
var toRename = args.toRename;
var toDeleteWorkflows = args.toDeleteWorkflows;
var toSpecializedType = args.toSpecializedType; // Contains the prefix (ie: toSpecializedType=sgf:invoiceCreditor)
// Qname finance
var qNameInvoiceCreditor = "{http://www.custom.ch/model/finance/1.0}invoiceCreditor";
var qNameInvoiceDebtor = "{http://www.custom.ch/model/finance/1.0}invoiceDebtor";
var qNamePaymentCreditor = "{http://www.custom.ch/model/finance/1.0}paymentCreditor";
var qNamePaymentDebtor = "{http://www.custom.ch/model/finance/1.0}paymentDebtor";
var qNameFinancialAccount = "{http://www.custom.ch/model/finance/1.0}financialAccount";
var qNameCondensedAccount = "{http://www.custom.ch/model/finance/1.0}condensedAccount";
// Information about webscript
var nameWebscriptUser = "Webscript custom Modify" + " by "
+ person.properties.userName;
var arguments = "Arguments : ";
var CONSUMER = "Consumer";
var CONTRIBUTOR = "Contributor";
var COORDINATOR = "Coordinator"
var GROUP_MANAGER = "GROUP_ManagerErp";
var GROUP_MANAGER_WF = "GROUP_WorkflowErp";
var GROUP_INFO = "GROUP_InfoErp";
var INITIATOR_WORKFLOW = "workflowslgged";
var response = "";
script: {
// Show arguments
for (arg in args) {
arguments += arg + "=" + args[arg] + ";";
}
logger.log(nameWebscriptUser + ". " + arguments);
// Verify the arguments
if (nodeReference == null || nodeReference == "") {
status.code = 400;
status.message = "Need to specify the nodeReference";
status.redirect = true;
break script;
} else {
node = search.findNode(nodeReference);
if (node != null) {
// Get current properties
var firmNbOrg = node.properties["sg:firmNb"];
var documentNbOrg = node.properties["sg:documentNb"];
var parentNodeOrg = node.parent;
// output….
response += "\t<message>This properties have been modified</message>\n";
response += "\t<properties>\n";
// Specialized the document to another type ?
if (toSpecializedType != null) {
specializedType();
}
// Set attributes (firmNb, documentNb, …)
setAttributes();
// Related to
if (relatedTo != null && relatedTo != "") {
setRelatedTo();
}
// Save (before adding aspect)
node.save();
// Threated document
var doesModifyAspect = toTreated + responsible;
if (doesModifyAspect != null && doesModifyAspect != "") {
addTreatedAspect();
}
// Move document
if (toMove != null && toMove == "true") {
// Do not move if the document is in workflow because it will move otherwise.
if (nameWorkflowToStart == null || nameWorkflowToStart == "") {
moveDocument();
}
}
// Delete document
if (toDelete != null && toDelete == "true") {
deleteMove();
// Delete all workflows
webscriptsHelper.deleteWorkflows(nodeReference,firmNbOrg,documentNbOrg,parentNodeOrg.nodeRef);
}
// Delete workflows
if (toDeleteWorkflows != null && toDeleteWorkflows == "true") {
// Delete all workflows
webscriptsHelper.deleteWorkflows(nodeReference,firmNbOrg,documentNbOrg,parentNodeOrg.nodeRef);
}
// Rename document
if (toRename != null && toRename == "true") {
rename();
} else if (fileName != null && fileName != "") {
node.properties["cm:name"] = fileName;
response += "\t\t<fileName>" + fileName + "</fileName>\n";
// Save
node.save();
}
// output….
response += "\t</properties>\n";
// Return message
status.message = response;
logger.log(nameWebscriptUser + ". \n" + response);
} else {
status.code = 400;
status.message = "Unable to find the nodeReference (use the webscript '/custom/search…' to have a right nodeRefence)";
logger
.log(nameWebscriptUser
+ ". ERROR : Unable to find the nodeReference (use the webscript '/custom/search…' to have a right nodeRefence)");
status.redirect = true;
}
}
}
/*
* Specialized the type of the document
*/
function specializedType() {
if (node.specializeType(toSpecializedType)){
response +="\t\t<type>" + toSpecializedType + "</type>\n";
}else{
response +="Error : Unable to set this type : "+toSpecializedType+". The document must be a parent (in the model).";
}
node.save();
}
/*
* Rename the document
* TODO do better : The check name add a random value also if a file is alone (a.pdf will be rename in x_a.pdf because the check will see the a.pdf)
*/
function rename() {
var firmNb_ = node.properties["sg:firmNb"];
var documentNb_ = node.properties["sg:documentNb"];
var oldName = node.properties["cm:name"];
var extension = "";
var type_ = node.type;
// Set extension
if (oldName.lastIndexOf('.') > 0) {
extension = oldName.substring(oldName.lastIndexOf('.'), oldName.length);
newName = newName + extension;
}
// Remove {…}type
type_ = type_.substring(type_.indexOf('}') + 1);
// new Name
var newName = type_ + "_" + firmNb_ + "_" + documentNb_ + extension;
var currentTime = new Date();
// Test if a node with same name exist
while (node.parent.childByNamePath(newName) != null) {
newName = Math.floor(Math.random() * 10) + "_" + newName;
}
// Write
node.properties["cm:title"] = newName;
node.properties["cm:name"] = newName;
response += "\t\t<fileName>" + newName + "</fileName>\n";
// Save
node.save();
}
/*
* Delete the document (move it)
*/
function deleteMove() {
// (Add) Modifiy Aspect property
node.addAspect("sg:deletable");
node.properties["sg:toDelete"] = false;// NEED to update a
// property to start an
// update process in the
// rule
node.save();
node.properties["sg:toDelete"] = true;
// Dont forget to add the rule to move depending of this aspect.
response += "\t\t[The aspect deletable (toDelete) has been setted]\n";
// Save
node.save();
}
/*
* Set the related to
*/
function setRelatedTo() {
//Concern customerNb
if (node.type == qNameInvoiceDebtor || node.type == qNamePaymentDebtor) {
node.properties["sg:customerNb"] = relatedTo;
response += "\t\t<customerNb>" + relatedTo + "</customerNb>\n";
// Concern distributorNb
} else if (node.type == qNameInvoiceCreditor
|| node.type == qNamePaymentCreditor) {
node.properties["sg:distributorNb"] = relatedTo;
response += "\t\t<distributorNb>" + relatedTo + "</distributorNb>\n";
}
// TODO
else if (false) {
node.properties["sg:studentNb"] = relatedTo;
response += "\t\t<studentNb>" + relatedTo + "</studentNb>\n";
// TODO
} else if (false) {
node.properties["sg:collaboratorNb"] = relatedTo;
response += "\t\t<collaboratorNb>" + relatedTo + "</collaboratorNb>\n";
}
}
/*
* Add the treated aspect
*/
function addTreatedAspect() {
// (Add) Modifiy Aspect property
node.addAspect("sg:treatable");
// node.save();
if (toTreated != null && toTreated != "") {
node.properties["sg:toTreated"] = toTreated;
response += "\t\t<toTreated>" + toTreated + "</toTreated>\n";
}
if (responsible != null && responsible != "") {
node.properties["sg:responsible"] = responsible;
response += "\t\t<responsible>" + responsible + "</responsible>\n";
}
// Save
node.save();
}
/*
* Move the document.
*/
function moveDocument() {
// (Add) Modifiy Aspect property
node.addAspect("sg:displaceable");
node.properties["sg:toDisplace"] = false;// NEED to update a
// property to start
// an update process
// in the rule
node.save();
node.properties["sg:toDisplace"] = true;
// Dont forget to add the rule to move depending of this aspect.
response += "\t\t[The aspect displaceable (toMove) has been setted]\n";
// Save
node.save();
}
/*
* Set attributes to the document
*/
function setAttributes() {
if (firmNb != null && firmNb != "") {
node.properties["sg:firmNb"] = firmNb;
response += "\t\t<firmNb>" + firmNb + "</firmNb>\n";
}
if (documentNb != null && documentNb != "") {
node.properties["sg:documentNb"] = documentNb;
response += "\t\t<documentNb>" + documentNb + "</documentNb>\n";
}
// Specialized
if (bvr != null && bvr != "") {
node.properties["sgf:bvr"] = bvr;
response += "\t\t<bvr>" + bvr + "</bvr>\n";
}
}
/*
* Convert date : "31.12.2011" in date Format.
*/
function convertStringPointToDate(stringDate){
var dueDateNewFormat=stringDate.split('.');
var dueDateDateFormat=new Date(0);
/* Month with setMonth : Jan=0, Dec=11 */
var month = dueDateNewFormat[1];
month -= 1;
if (month < 0){
month = 11;
}
dueDateDateFormat.setDate(dueDateNewFormat[0]);
dueDateDateFormat.setMonth(month);
dueDateDateFormat.setFullYear(dueDateNewFormat[2]);
return dueDateDateFormat;
}
Arguments envoyés au webscript
toMove=true;relatedTo=10012;nodeReference=workspace://SpacesStore/99131585-c8c7-45bf-82e0-…;firmNb=1;toTreated=false;toRename=true;toSpecializedType=sgf:invoiceDebtor;documentNb=1045295;alf_ticket=TICKET_9414f2d27baf90619eecd3b1bb…;
Bien que le problème ne vienne pas de la, je suis un peu perplexe sur vos fonctions JavaScript qui ne prennent aucun paramètre en entrée et qui utilisent des variables globales … (specializedType(), setAttributes(), …)Le codage peut être amélioré je suis d'accord.
je trouve qu'il y a beaucoup de .save(), certains ne semble pas nécessaireLe code a été développé en 32r2. Certains .save() qui pourraient paraître superflux étaient nécessaire…
Travaillez vous sur une grosse volumétrie ? Si c'est le cas, il faudrait peut être envisager de jouer avec certains paramètres Lucene.Plus de 20'000 documents en tout, et plus de 2'000 pour les invoiceDebtor.
Est-il possible que vos recherches retournent plus de 1000 résultats ?
#
# Properties to limit resources spent on individual searches
# (Useful for the script test SearchRedundant. It allow to show more 1000 documents)
# The maximum time spent pruning results (*********I Changed from 10000 to 100000)
system.acl.maxPermissionCheckTimeMillis=100000
# The maximum number of results to perform permission checks against (*********I Changed from 1000 to 10000)
system.acl.maxPermissionChecks=10000
Mais je ne pense pas que cela soit lié car avec Luke j'ai affiché tous les résultats dans un tableau et j'ai contrôlé la présence des fichiers disparus… et ils n'y étaient pas…
Content from pre 2016 and from language groups that have been closed.
Content is read-only.
By using this site, you are agreeing to allow us to collect and use cookies as outlined in Alfresco’s Cookie Statement and Terms of Use (and you have a legitimate interest in Alfresco and our products, authorizing us to contact you in such methods). If you are not ok with these terms, please do not use this website.