CMDBuild Forum

How to keep maintenance records

Let’s say that I have a Class and several Cards.
For each of the cards from time to time I am doing some maintenance.
Each maintenance ends with report in which all used materials (quantities and prices) are specified.

When I am on particular Card, I would like to see history of all such reports.
How to set this in cmdbuild?



not sure if this is what you are looking for … but on each card you have the ability to add “attachments”. If you can produce your reports and export them into pdf or xlsx or whatever format, you can then add these reports as attachments to you corresponding card.

All you need to do is to enable the Alfresco DMS on your server to enable attachments on cards and obviously grant the necessary permissions to you different profiles.

You can also use the scheduler to schedule some kind of a process in CMDB (e.g. generate report), or if you edit a card and edit a given attribute, then you can write a trigger in the database to process some data. This trigger can also fire an event, that a postgresql client application can catch and then do additional processing.

I hope with these ideas, you’ll be able to find a solution that fits your needs.

Hi Alex,

if I use Alfresco DMS and attachment option in order to attach documents, let’s say excel files, will I be able to search through excels for particular item number/description?

Let’s say that I have a card with several attached excel files.
Will I be able to search for all excels in which there is item number 00005?

It would be very very nice if I can also search through all cards in order to find out on which card a certain item has been replaced (information in attached excel files).
Can Alfresco support such option?

I don’t have an experience with Alfresco (or any other) DMS, so I don’t know is this search responsibility of CMDBuild or Alfresco.

Another question is regarding database triggers you have mentioned.
In postgresql, in trigger, can I send some information to external REST system by?

Best regards.

If all you want to see is the list of changes that were made to a card, you can see it in the History tab in an opened card.

History tab is not so concise.

I would like to see records like:
maintenance type, date, status, costs
(one row, one maintenance)

I would also like to filter maintenance records by maintenance type in order to see the first maintenance of the selected type or the last one (sorting).
Something like excel table would be the best, or something similar.

How can I come the closest to this requirement in CMDBuild?
How are you presenting maintenance records to the end users?
What is your practice?
At one point every user would like to know history of the maintenance by different criteria.
Maybe the report is the only option.


you can search in the attachments list, but I don’t think this search “looks” inside the documents. Alfresco can index documents but I’m not sure cmdb will use these indexes.

From postgresql you can’t directly call a REST service, at least not if you don’t install some kind of extension I think. But in a trigger you can fire an event. You can then write you custom “broker” that connects to your postgresql database and listens to these events (you can have different topics), this broker can then call a REST service.

That’s the way I’m using it …

The event you fire in postgresql contains the channel name and a payload. The payload can be some JSON string if you need it or just the ID of the card you want to process in your service.

As far as I remember there is currently a restriction (Java driver?) that forces you to use polling to retrieve the events from the database. So my broker runs as a scheduler job in an Apache Karaf. It then calls a dedicated service for the different channels.


In the CMDBuild 3.3.1 version, which will be released towards the end of this month, the search within some types of attached files has also been introduced.

It is good to know that. Can you be more specific about an expression “some types of attached files”?


when you said: “…in a trigger you can fire an event…”, do you mean that in the trigger I will insert a new record to some other table from which I will periodically (broker) select records in order to find out if there are any new events, or the idea is different?

Please confirm.


I have a card that has an attribute “NetworkSecurity”. If that attribute is changed I want to notify an external service that updates settings in our LDAP based on the change. So in my trigger function for that card I do the following:

	if (new."NetworkSecurity" is not null and new."NetworkSecurity" <> old."NetworkSecurity") then 
			with payload(topic, building, nwsecurity, tstp) as (
				select 'network_security_change' as topic, new."Code" as building, (select "Code" from "LookUp" lu where lu."Id" = new."NetworkSecurity" and lu."Status" = 'A') as nwsecurity, now() as tstp
			select pg_notify('your_channel_name', row_to_json(payload)::text) from payload
	end if;

Then I have my “broker” program checking for the notifications:

private void checkForNotifications() {
	try {
		PGNotification notifications[] = pgConnection.getNotifications();
		if (notifications == null || notifications.length == 0) {"No notifications received");
		for (PGNotification notification : notifications) {"Notification {} with parameter {} received", notification.getName(), notification.getParameter());
            Map<String, String> parameters = CmdbuildReady2UseChangeListerServiceImpl.OBJECT_MAPPER.readValue(notification.getParameter(), new TypeReference<Map<String, String>>(){});
            String topic = parameters.get("topic");
            if (topic != null && changeListenerServices.containsKey(topic)) {"Notification is for topic {} and we have a service available", topic);

				// now process your notification ...
            } else if (topic == null) {
				LOGGER.error("No topic attribute found in payload");
            } else if (!changeListenerServices.containsKey(topic)) {
            	LOGGER.warn("No service available for topic {}", topic);
	} catch (final SQLException e) {
	} catch (final IOException e) {

Here I read the notifications from my postgresql connection. I unmarshall the JSON payload and look for my topic attribute (in this case the “network_security_change” set in the trigger).
If the notification contains a topic and if I have a service that can handle these notifications (hashmap look “changeListenerServices.containsKey(topic)”) then I can process the messages.

This is how I connect to the database and listen for the notifications:
connection = dataSource.getConnection();
pgConnection = connection.unwrap(PGConnection.class);
Statement statement = connection.createStatement();
statement.execute("LISTEN " + “your_channel_name”);

Hope this clarifies a little bit


1 Like

Alex, thank you very very much for everything you have provided here.
You clarified really a lot to me.
Best regards. :+1:

You’re welcome, hope it helps.

It really helps.
Thanks again.

Best regards.