====== Dolibarr ====== Définition de la table actioncomm: [[http://wiki.dolibarr.org/index.php/Table_llx_actioncomm|http://wiki.dolibarr.org/index.php/Table_llx_actioncomm]] ===== Insertion d'un rendez-vous / événement unique ===== INSERT INTO llx_actioncomm (datec,datep,datep2,durationp,fk_action,code,fk_soc,fk_project,note,fk_contact,fk_user_author,fk_user_action,fk_user_done,label,percent,priority,fulldayevent,location,punctual,transparency,fk_element,elementtype,entity) VALUES ('20131213105345','20131213121500','20131213131500','3600',50,NULL,NULL,NULL, //,NULL,'1','1',NULL,'test d'agenda','-1','0','0',//,'1','0',null,null,1) ===== Rendez-vous / événement sur une journée ===== La différence intervient sur le champ booléen 'fulldayevent' INSERT INTO llx_actioncomm (datec,datep,datep2,durationp,fk_action,code,fk_soc,fk_project,note,fk_contact,fk_user_author,fk_user_action,fk_user_done,label,percent,priority,fulldayevent,location,punctual,transparency,fk_element,elementtype,entity) VALUES ('20131217222748','20131227000000','20131227235959','86399',50,NULL,NULL,NULL, 'Gros event de ouf !!! Soirée Trigger Sexy',NULL,'2','2',NULL,'Salon de la synchronisation','-1','0','1','Sur mon bureau','1','0',NULL,NULL,1) ===== Modification d'un rendez-vous ===== La distinction entre un événement 'unique' et une journée complète est toujours lié au champ 'fulldayevent' UPDATE llx_actioncomm SET percent = '-1', label = 'le 26 on mange du SQL en force', datep = '20131226000000', datep2 = NULL, note = 'Et c''est toute la journée', fk_soc =NULL, fk_project =NULL, fk_contact =NULL, priority = '0', fulldayevent = '1', location = 'Ou tu veux', transparency = '0', fk_user_mod = '2', fk_user_action='2', fk_user_done=NULL WHERE id=1 ====== ATmail ====== ATmail repose sur le standard iCalendar: [[http://fr.wikipedia.org/wiki/ICalendar|http://fr.wikipedia.org/wiki/ICalendar]] ===== Insertion d'un rendez-vous / événement unique ===== INSERT INTO `calendarObjects` (calendarid, uri, calendardata, lastmodified, START, END, rrule) VALUES ('2','3cedcfbd-925b-4786-a81f-f401942e859f.ics','BEGIN:VCALENDARrnVERSION:2.0rnPRODID:-//Atmail//6.0//ENrnCALSCALE:GREGORIANrnBEGIN:VEVENTrnSEQUENCE:1rnTRANS:OPAQUErnUID:3cedcfbd-925b-4786-a81f-f401942e859frnDTSTART;VALUE=date:20140113rnDTEND:20140114rnSUMMARY:Nouvel événementrnDESCRIPTION:rnDTSTAMP:20131213T134312ZrnEND:VEVENTrnEND:VCALENDARrn','1386942192','1389571200','1389657600','0') UPDATE `calendars` SET ctag = ctag + 1 WHERE id = '2' UPDATE `calendarObjects` SET calendardata = 'BEGIN:VCALENDARrnVERSION:2.0rnPRODID:-//Atmail//6.0//ENrnCALSCALE:GREGORIANrnBEGIN:VEVENTrnSEQUENCE:2rnTRANS:OPAQUErnUID:3cedcfbd-925b-4786-a81f-f401942e859frnDTSTART:20140113T090000rnDTEND:20140113T100000rnSUMMARY:CopilrnDESCRIPTION:rnDTSTAMP:20131213T134554ZrnLAST-MODIFIED:20131213T134554ZrnLOCATION:test du deuxieme champ librernCATEGORY:BusinessrnAVAILABILITY:BusyrnBEGIN:VALARMrnTRIGGER:-PT15HrnDESCRIPTION:Alarm for: "Copil"rnACTION:DISPLAYrnEND:VALARMrnRRULE:FREQ=DAILY;INTERVAL=1rnRRULE2:FREQ=DAILY;COUNT=400rnEND:VEVENTrnEND:VCALENDARrn', lastmodified = '1386942354', START = '1389603600', END = '1389607200', rrule = '1' WHERE calendarid = '2' AND uri = '3cedcfbd-925b-4786-a81f-f401942e859f.ics' UPDATE calendars SET ctag = ctag + 1 WHERE id = '2' ===== Rendez-vous / événement sur une journée ===== La différence intervient dans le champ calendardata sur les propriétés DTSTART et DTEND. UPDATE `calendarObjects` SET calendardata = 'BEGIN:VCALENDARrnVERSION:2.0rnPRODID:-//Atmail//6.0//ENrnCALSCALE:GREGORIANrnBEGIN:VEVENTrnSEQUENCE:2rnTRANS:OPAQUErnUID:6626c386-2507-4669-a85f-fb75cc13e1ecrnDTSTART;VALUE=DATE:20131217rnDTEND;VALUE=DATE:20131218rnSUMMARY:journee fulrnDESCRIPTION:rnDTSTAMP:20131217T210820ZrnLAST-MODIFIED:20131217T210820ZrnLOCATION:chez toirnCATEGORY:GeneralrnAVAILABILITY:BusyrnEND:VEVENTrnEND:VCALENDARrn', lastmodified = '1387314501', START = '1387238400', END = '1387324800', rrule = '0' WHERE calendarid = '10' AND uri = '6626c386-2507-4669-a85f-fb75cc13e1ec.ics' ===== Modification d'un rendez-vous ===== Pour le suivi des modification, le paramètre "SEQUENCE" dans le champ calendardata doit être incrémenté de +1. UPDATE calendarObjects SET calendardata = 'BEGIN:VCALENDARrnVERSION:2.0rnPRODID:-//Atmail//6.0//ENrnCALSCALE:GREGORIANrnBEGIN:VEVENTrnSEQUENCE:2rnTRANS:OPAQUErnUID:eaa361e1-70dc-cc21-1c88-fcf20226332d3ernDTSTART;VALUE=DATE:20131226rnDTEND;VALUE=DATE:20131226rnSUMMARY:le 26 on mange du SQLrnDESCRIPTION:Et c''est toute la journéernDTSTAMP:20131218T151600ZrnLAST-MODIFIED:20131218T151600ZrnLOCATION:Ou tu veuxrnCATEGORY:BusinessrnAVAILABILITY:BusyrnORGANIZER;CN=bperrin@nimbo.lan:MAILTO:bperrin@nimbo.lanrnEND:VEVENTrnEND:VCALENDARrn', lastmodified = '1387379761', START = '1388016000', END = '1388016000', rrule = '0' WHERE calendarid = '10' AND uri = 'eaa361e1-70dc-cc21-1c88-fcf20226332d3e.ics' UPDATE calendars SET ctag = ctag + 1 WHERE id = '10' ====== Synchronisation Dolibarr/Agenda vers Atmail ====== * Les dates Dolibarr sont formatées avec des '-' et des ':', celle de Atmail sans, il faut donc les supprimés, j'ai créé la fonction split_string pour effectuer les découpes et la fonction dateERP2ATMAIL pour concaténé les découpes et géré la valeur retourné en function de l'événement (journée complète ou non). * La création d'un événement iCal est intégré dans un champ unique nommé calendardata, ce champ à toutes les informations sur l'événement. * Si le champ "elementtype" de dolibarr est différent de Null on ne créé pas d'événement dans Atmail car il correspond à un événement système dans Dolibarr * *Il est nécessaire de créer un identifiant unique pour un événément, pour ce faire, j'ai créé la formule suivante: MD5( CONCAT( NEW.id, [[:systeme_informatique:atmail:timestampcreateutc|TimeStampCreateUTC]], [[:systeme_informatique:atmail:owneratmail|OwnerAtmail]],(SELECT RAND()))); * On concatène l'id de l'événement dolibarr avec le timestamp de création (dolibarr), le nom du proprietaire de l'événement atmail et un nombre alétoire, tout cela hashé par un MD5. * Les entrées DTSTART, DTEND, LAST-MODIFIED, DTSTAMP demande un format particulier * La category est fixé sur Business * Si dans dolibarr ont spécifie que cette événement est associé à un utilisateur autre que le créateur, alors on créé l'événement dans l'agenda de l'utilisateur en question * On récupère l'id du calendrier 'private' pour mettre à jour le compteur ctag * Utilisation du champ PRODID pour stocker l'id dolibarr ===== Trigger MYSQL après un INSERT calendar dans Dolibarr: after_insert_actioncomm ===== DELIMITER ; DROP FUNCTION IF EXISTS split_string; DROP FUNCTION IF EXISTS dateERP2ATMAIL; DROP TRIGGER after_insert_actioncomm; DELIMITER // CREATE FUNCTION split_string (stringToSplit VARCHAR(256), sign VARCHAR(12), POSITION INT(2)) RETURNS VARCHAR(255) BEGIN RETURN REPLACE(SUBSTRING(SUBSTRING_INDEX(stringToSplit,sign,POSITION),LENGTH(SUBSTRING_INDEX(stringToSplit, sign, POSITION -1)) + 1), sign, //); END// CREATE FUNCTION dateERP2ATMAIL(DATE VARCHAR(255),Format VARCHAR(5)) RETURNS VARCHAR(255) BEGIN DECLARE YEAR CHAR(4); DECLARE MONTH CHAR(2); DECLARE DAY CHAR(2); DECLARE HOUR CHAR(2); DECLARE MINUTE CHAR(2); DECLARE Seconde CHAR(2); DECLARE DateSplit CHAR(10); DECLARE TimeSplit CHAR(8); SET DateSplit = (SELECT split_string(DATE,' ', 1) AS name); SET TimeSplit = (SELECT split_string(DATE,' ', 2) AS name); SET YEAR = (SELECT split_string(DateSplit,'-', 1) AS name); SET MONTH = (SELECT split_string(DateSplit,'-', 2) AS name); SET DAY = (SELECT split_string(DateSplit,'-', 3) AS name); SET HOUR = (SELECT split_string(TimeSplit,':', 1) AS name); SET MINUTE = (SELECT split_string(TimeSplit,':', 2) AS name); SET Seconde = (SELECT split_string(TimeSplit,':', 3) AS name); IF(Format = "all") THEN RETURN CONCAT(YEAR,MONTH,DAY,'T',HOUR,MINUTE,Seconde); ELSE RETURN CONCAT(YEAR,MONTH,DAY); END IF; END// DELIMITER // CREATE TRIGGER after_insert_actioncomm AFTER INSERT ON llx_actioncomm FOR EACH ROW BEGIN DECLARE Owner VARCHAR(255); DECLARE OwnerAtmail VARCHAR(255); DECLARE StartDate VARCHAR(30); DECLARE EndDate VARCHAR(30); DECLARE TimeStampStart VARCHAR(30); DECLARE TimeStampEnd VARCHAR(30); DECLARE TimeStampCreateUTC VARCHAR(30); DECLARE DtStampCreate VARCHAR(30); DECLARE TimeStampLastModifUTC VARCHAR(50); DECLARE LastModifiedUTC VARCHAR(50); DECLARE UidBase VARCHAR(50); DECLARE UidOk VARCHAR(50); DECLARE UriIcsFile VARCHAR(50); DECLARE IcsData MEDIUMTEXT; DECLARE IdCalendar INT(11); DECLARE FormatDate VARCHAR(10); DECLARE StringDate VARCHAR(20); IF ( NEW.elementtype = NULL ) THEN SET Owner = (SELECT login FROM llx_user WHERE rowid = NEW.fk_user_action); SET OwnerAtmail = (SELECT Account FROM atmail.Users WHERE Account = Owner); IF( NEW.fulldayevent=1 )THEN SET FormatDate = 'day'; SET TimeStampEnd = (SELECT unix_timestamp(NEW.datep)+86399); SET StringDate = (SELECT ";VALUE=DATE:"); ELSE SET FormatDate = 'all'; SET TimeStampEnd = (SELECT unix_timestamp(NEW.datep2)); SET StringDate = (SELECT ":"); END IF; SET StartDate = CONCAT(StringDate,(SELECT dateERP2ATMAIL(NEW.datep,FormatDate))); SET EndDate = CONCAT(StringDate,(SELECT dateERP2ATMAIL(NEW.datep,FormatDate))); SET TimeStampStart = (SELECT unix_timestamp(NEW.datep)); SET TimeStampCreateUTC = (SELECT unix_timestamp(NEW.datec)-3600); SET DtStampCreate = CONCAT((SELECT FROM_UNIXTIME(TimeStampCreateUTC,'%Y%m%d')),'T',(SELECT FROM_UNIXTIME(TimeStampCreateUTC,'%H%i%s')),'Z'); SET TimeStampLastModifUTC = (SELECT unix_timestamp(NEW.tms)-3600); SET LastModifiedUTC = CONCAT((SELECT FROM_UNIXTIME(TimeStampLastModifUTC,'%Y%m%d')),'T',(SELECT FROM_UNIXTIME(TimeStampLastModifUTC,'%H%i%s')),'Z'); SET UidBase = MD5(CONCAT(NEW.id,TimeStampCreateUTC,OwnerAtmail,(SELECT RAND()))); SET UidOk = concat(SUBSTRING(UidBase,1,8),'-',SUBSTRING(UidBase,9,4),'-',SUBSTRING(UidBase,12,4),'-',SUBSTRING(UidBase,15,4),'-',SUBSTRING(UidBase,19)); SET UriIcsFile = CONCAT(UidOK,'.ics'); SET IcsData = CONCAT("BEGIN:VCALENDARrn","VERSION:2.0rn","PRODID:-//Atmail//6.0//ENrn","CALSCALE:GREGORIANrn","BEGIN:VEVENTrn","SEQUENCE:1rn","TRANS:OPAQUErn", "UID:",UidOk,"rn","DTSTART",StartDate,"rn","DTEND",EndDate,"rn","SUMMARY:",NEW.label,"rn","DESCRIPTION:",NEW.note,"rn","DTSTAMP:",DtStampCreate,"rn","LAST-MODIFIED:", LastModifiedUTC,"rn","LOCATION:",NEW.location,"rn","CATEGORY:Businessrn","AVAILABILITY:Busyrn","ORGANIZER;CN=",OwnerAtmail,":MAILTO:",OwnerAtmail,"rn","END:VEVENTrn","END:VCALENDARrn"); SET IdCalendar = (SELECT id FROM atmail.calendars WHERE principaluri = CONCAT('principals/users/',OwnerAtmail) AND displayname = 'Private'); INSERT INTO atmail.calendarObjects (calendardata,uri,calendarid,lastmodified,START,END,rrule)VALUES(IcsData,UriIcsFile,IdCalendar,TimeStampLastModifUTC,TimeStampStart,TimeStampEnd,'0'); UPDATE atmail.calendars SET ctag = ctag + 1 WHERE id = IdCalendar; END IF; END// DELIMITER ; ===== Trigger MYSQL après un UPDATE calendar dans Dolibarr: after_update_actioncomm ===== DROP TRIGGER IF EXISTS after_update_actioncomm; DELIMITER // CREATE TRIGGER after_update_actioncomm AFTER UPDATE ON llx_actioncomm FOR EACH ROW BEGIN DECLARE Owner VARCHAR(255); DECLARE OwnerAtmail VARCHAR(255); DECLARE StartDate VARCHAR(30); DECLARE EndDate VARCHAR(30); DECLARE TimeStampStart VARCHAR(30); DECLARE TimeStampEnd VARCHAR(30); DECLARE TimeStampCreateUTC VARCHAR(30); DECLARE DtStampCreate VARCHAR(30); DECLARE CalendarObjectsId INT(11); DECLARE TimeStampLastModifUTC VARCHAR(50); DECLARE LastModifiedUTC VARCHAR(50); DECLARE UidBase VARCHAR(50); DECLARE UidOk VARCHAR(50); DECLARE UriIcsFile VARCHAR(50); DECLARE IcsData MEDIUMTEXT; DECLARE IdCalendar INT(11); DECLARE FormatDate VARCHAR(10); DECLARE StringDate VARCHAR(20); DECLARE DolActioncommId INT(11); DECLARE SEQUENCE INT(11); SET Owner = (SELECT login FROM llx_user WHERE rowid = OLD.fk_user_action); SET OwnerAtmail = (SELECT Account FROM atmail.Users WHERE Account = Owner); IF( NEW.fulldayevent=1 )THEN SET FormatDate = 'day'; SET TimeStampEnd = (SELECT unix_timestamp(NEW.datep)+86399); SET StringDate = (SELECT ";VALUE=DATE:"); ELSE SET FormatDate = 'all'; SET TimeStampEnd = (SELECT unix_timestamp(NEW.datep2)); SET StringDate = (SELECT ":"); IF(TimeStampEnd IS NULL)THEN SET TimeStampEnd = (SELECT unix_timestamp(NEW.datep)); END IF; END IF; SET StartDate = CONCAT(StringDate,(SELECT dateERP2ATMAIL(NEW.datep,FormatDate))); SET EndDate = CONCAT(StringDate,(SELECT dateERP2ATMAIL(NEW.datep,FormatDate))); SET TimeStampStart = (SELECT unix_timestamp(NEW.datep)); SET TimeStampCreateUTC = (SELECT unix_timestamp(OLD.datec)-3600); SET DtStampCreate = CONCAT((SELECT FROM_UNIXTIME(TimeStampCreateUTC,'%Y%m%d')),'T',(SELECT FROM_UNIXTIME(TimeStampCreateUTC,'%H%i%s')),'Z'); SET TimeStampLastModifUTC = (SELECT unix_timestamp(NEW.tms)-3600); SET LastModifiedUTC = CONCAT((SELECT FROM_UNIXTIME(TimeStampLastModifUTC,'%Y%m%d')),'T',(SELECT FROM_UNIXTIME(TimeStampLastModifUTC,'%H%i%s')),'Z'); SET DolActioncommId = OLD.id; SET IdCalendar = (SELECT id FROM atmail.calendars WHERE principaluri = CONCAT('principals/users/',OwnerAtmail) AND displayname = 'Private'); SET CalendarObjectsId = (SELECT calendarObjects.id FROM atmail.calendars LEFT JOIN atmail.calendarObjects ON calendars.id = calendarObjects.calendarid WHERE principaluri = CONCAT('principals/users/', OwnerAtmail) AND calendardata LIKE CONCAT('%DOLID#',OLD.id,'#%')); IF(CalendarObjectsId IS NULL)THEN SET UidBase = MD5(CONCAT(NEW.id,TimeStampCreateUTC,OwnerAtmail,(SELECT RAND()))); SET UidOk = concat(SUBSTRING(UidBase,1,8),'-',SUBSTRING(UidBase,9,4),'-',SUBSTRING(UidBase,12,4),'-',SUBSTRING(UidBase,15,4),'-',SUBSTRING(UidBase,19)); SET UriIcsFile = CONCAT(UidOK,'.ics'); SET IcsData = CONCAT("BEGIN:VCALENDAR","VERSION:2.0","PRODID:-//Atmail//6.0//EN//DOLID#",DolActioncommId,"#","","CALSCALE:GREGORIAN","BEGIN:VEVENT","SEQUENCE:1","TRANS:OPAQUE","UID:",UidOk,"","DTSTART",StartDate,"","DTEND",EndDate,"","SUMMARY:",NEW.label,"","DESCRIPTION:",NEW.note,"","DTSTAMP:",DtStampCreate,"","LAST-MODIFIED:", LastModifiedUTC,"","LOCATION:",NEW.location,"","CATEGORY:Business","AVAILABILITY:Busy","ORGANIZER;CN=",OwnerAtmail,":MAILTO:",OwnerAtmail,"","END:VEVENT","END:VCALENDAR"); INSERT INTO atmail.calendarObjects (calendardata,uri,calendarid,lastmodified,START,END,rrule)VALUES(IcsData,UriIcsFile,IdCalendar,TimeStampLastModifUTC,TimeStampStart,TimeStampEnd,'0'); UPDATE atmail.calendars SET ctag = ctag + 1 WHERE id = IdCalendar; ELSE SET IcsData = (SELECT calendardata FROM atmail.calendarObjects WHERE id = CalendarObjectsId); SET SEQUENCE = (SELECT (SUBSTRING(IcsData, INSTR(IcsData,"SEQUENCE:")+9, INSTR(IcsData,"TRANS:")-(INSTR(IcsData,"SEQUENCE:")+9)))+1); SET UidOk = (SELECT LEFT((SELECT uri FROM atmail.calendarObjects WHERE id = CalendarObjectsId ), 38)); SET UriIcsFile = CONCAT(UidOK,'.ics'); SET IcsData = CONCAT("BEGIN:VCALENDAR","VERSION:2.0","PRODID:-//Atmail//6.0//EN//DOLID#",DolActioncommId,"#","","CALSCALE:GREGORIAN","BEGIN:VEVENT","SEQUENCE:",SEQUENCE,"","TRANS:OPAQUE","UID:",UidOk,"","DTSTART",StartDate,"","DTEND",EndDate,"","SUMMARY:",NEW.label,"","DESCRIPTION:",NEW.note,"","DTSTAMP:",DtStampCreate,"","LAST-MODIFIED:", LastModifiedUTC,"","LOCATION:",NEW.location,"","CATEGORY:Business","AVAILABILITY:Busy","ORGANIZER;CN=",OwnerAtmail,":MAILTO:",OwnerAtmail,"","END:VEVENT","END:VCALENDAR"); UPDATE atmail.calendarObjects SET calendardata = IcsData, lastmodified=TimeStampLastModifUTC, START=TimeStampStart, END=TimeStampEnd, rrule='0' WHERE calendarid=IdCalendar AND uri=UriIcsFile; UPDATE atmail.calendars SET ctag = ctag + 1 WHERE id = IdCalendar; END IF; END // DELIMITER ; ====== Autre solution ====== Projet de synchronisation de l'agenda dolibarr et atmail dans les deux sens : \\ \\ L'idée est de considérer dolibarr comme un client mobile ‘iphone’ et atmail comme le serveur : \\ \\ • toutes les modifications de l’agenda atmail seront importées dans dolibarr, par exemple quand on cliquera sur l’icône Agenda de dolibarr : il … \\ • les modifications faîtes dans l’agenda dolibarr seront automatiquement envoyées sur atmail \\ \\ Remarque : dans la configuration dolibarr Configuration > Agenda > Import Calendrier Externe on peut spécifier une url pointant sur un fichier ICS (cela peut être votre agenda Gmail ; dans Gmail aller sur Agenda > Partager > Detail du partager > URL ICAL) : cela permet déjà de voir comme fonctionne la synchro dolibarr / Gmail/ \\ \\ dolibarr utilise à priori le fichier comm/action/ical.class.php ([[http://www.on-tech.gr/crm/dolibarr/build/html/d2/d56/ical_8class_8php_source.html|http://www.on-tech.gr/crm/dolibarr/build/html/d2/d56/ical_8class_8php_source.html]]) qui manipuler du ics. \\ \\ \\ Pour manipuler le caldav dans dolibarr on s'authentifiera avec la librairie php [[:systeme_informatique:atmail:sabredav|SabreDAV]] ([[http://en.wikipedia.org/wiki/SabreDAV|http://en.wikipedia.org/wiki/SabreDAV]]) (peut etre trop fonctionnel, mais on peut s'en inspirer). \\ \\ Les données vcalendar d’atmail se trouve dans le champ calendardata de la table calendarObjects.