Expand my Community achievements bar.

SOLVED

Completion date calculated based on a start date and an amount from a number field.

Avatar

Level 6

Has anyone scripted a completion date (date field) to be calculated based on a user entered start date(date field) + user entered number of days(number field)? If so, do you mind sharing or point me to the proper thread?

 

(Use case: A contractor chooses a start date for a job, and then enters the number of days the project will last, then the ending date is calculated based on the starting date + job length...we do not need to exclude the weekends.)

 

Thanks!

1 Accepted Solution

Avatar

Correct answer by
Employee Advisor

I am sharing one sample implementation hope this will help -

 

Here is the component's Touch UI dialog editor with field details-

 

DEBAL_DAS_0-1647761004522.png

 

.content.xml of cq:dialog -

<?xml version="1.0" encoding="UTF-8"?>
<jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/1.0" xmlns:cq="http://www.day.com/jcr/cq/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0" xmlns:nt="http://www.jcp.org/jcr/nt/1.0"
jcr:primaryType="nt:unstructured"
jcr:title="Application"
sling:resourceType="cq/gui/components/authoring/dialog">
<content
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/fixedcolumns">
<items jcr:primaryType="nt:unstructured">
<column
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/container">
<items jcr:primaryType="nt:unstructured">
<noofdays
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/form/numberfield"
fieldLabel="Number of Days"
name="./noofdays"
step="1"/>
<startdate
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/form/datepicker"
displayedFormat="YYYY-MM-DD HH:mm"
fieldLabel="Start Date"
name="./startdate"
renderReadOnly="{Boolean}false"
type="date"/>
<calculateddate
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/form/datepicker"
disabled="{Boolean}true"
displayedFormat="YYYY-MM-DD HH:mm"
fieldLabel="Calculated Date"
name="./calculateddate"
type="date"/>
</items>
</column>
</items>
</content>
</jcr:root>

 

Business logic like completion date (date field) to be calculated based on a user entered start date(date field) + user entered number of days(number field) is part of my sling model -

 

package com.aem.demo.core.models;

import java.time.LocalDate;
import java.time.ZoneId;
import java.util.Calendar;
import java.util.Date;
import java.util.Objects;

import javax.annotation.PostConstruct;
import javax.jcr.Node;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.ValueFormatException;
import javax.jcr.lock.LockException;
import javax.jcr.nodetype.ConstraintViolationException;
import javax.jcr.version.VersionException;

import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.models.annotations.DefaultInjectionStrategy;
import org.apache.sling.models.annotations.Model;
import org.apache.sling.models.annotations.injectorspecific.SlingObject;
import org.apache.sling.models.annotations.injectorspecific.ValueMapValue;

@Model(adaptables = SlingHttpServletRequest.class, defaultInjectionStrategy = DefaultInjectionStrategy.OPTIONAL)
public class CompletionDateModel {

@ValueMapValue
private String noofdays;

@ValueMapValue
private Date startdate;

@ValueMapValue
private Date calculateddate;

@SlingObject
SlingHttpServletRequest slingHttpServletRequest;

@PostConstruct
protected void init() {
if (Objects.nonNull(noofdays)) {
long userEnteredDate = Long.parseLong(noofdays);

LocalDate localStartDate = startdate.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
LocalDate plusDays = localStartDate.plusDays(userEnteredDate);
calculateddate = Date.from(plusDays.atStartOfDay(ZoneId.systemDefault()).toInstant());
Calendar calendar = Calendar.getInstance();
calendar.setTime(calculateddate);

Node currentnode = slingHttpServletRequest.getResource().adaptTo(Node.class);

Session session = slingHttpServletRequest.getResourceResolver().adaptTo(Session.class);
try {
currentnode.setProperty("calculateddate", calendar);
session.save();
} catch (ValueFormatException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (VersionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (LockException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ConstraintViolationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (RepositoryException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

}

}

/**
* @Return the noofdays
*/
public String getNoofdays() {
return noofdays;
}

/**
* @Return the startdate
*/
public Date getStartdate() {
return startdate;
}

}

 

Validating field values on different pages -

DEBAL_DAS_1-1647762442797.png

DEBAL_DAS_2-1647762472310.png

 

Persisted data at component node level -

 

DEBAL_DAS_3-1647762663421.png

 

I feel we could give a try to process the data for completion date field using JS also.

View solution in original post

2 Replies

Avatar

Correct answer by
Employee Advisor

I am sharing one sample implementation hope this will help -

 

Here is the component's Touch UI dialog editor with field details-

 

DEBAL_DAS_0-1647761004522.png

 

.content.xml of cq:dialog -

<?xml version="1.0" encoding="UTF-8"?>
<jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/1.0" xmlns:cq="http://www.day.com/jcr/cq/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0" xmlns:nt="http://www.jcp.org/jcr/nt/1.0"
jcr:primaryType="nt:unstructured"
jcr:title="Application"
sling:resourceType="cq/gui/components/authoring/dialog">
<content
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/fixedcolumns">
<items jcr:primaryType="nt:unstructured">
<column
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/container">
<items jcr:primaryType="nt:unstructured">
<noofdays
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/form/numberfield"
fieldLabel="Number of Days"
name="./noofdays"
step="1"/>
<startdate
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/form/datepicker"
displayedFormat="YYYY-MM-DD HH:mm"
fieldLabel="Start Date"
name="./startdate"
renderReadOnly="{Boolean}false"
type="date"/>
<calculateddate
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/form/datepicker"
disabled="{Boolean}true"
displayedFormat="YYYY-MM-DD HH:mm"
fieldLabel="Calculated Date"
name="./calculateddate"
type="date"/>
</items>
</column>
</items>
</content>
</jcr:root>

 

Business logic like completion date (date field) to be calculated based on a user entered start date(date field) + user entered number of days(number field) is part of my sling model -

 

package com.aem.demo.core.models;

import java.time.LocalDate;
import java.time.ZoneId;
import java.util.Calendar;
import java.util.Date;
import java.util.Objects;

import javax.annotation.PostConstruct;
import javax.jcr.Node;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.ValueFormatException;
import javax.jcr.lock.LockException;
import javax.jcr.nodetype.ConstraintViolationException;
import javax.jcr.version.VersionException;

import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.models.annotations.DefaultInjectionStrategy;
import org.apache.sling.models.annotations.Model;
import org.apache.sling.models.annotations.injectorspecific.SlingObject;
import org.apache.sling.models.annotations.injectorspecific.ValueMapValue;

@Model(adaptables = SlingHttpServletRequest.class, defaultInjectionStrategy = DefaultInjectionStrategy.OPTIONAL)
public class CompletionDateModel {

@ValueMapValue
private String noofdays;

@ValueMapValue
private Date startdate;

@ValueMapValue
private Date calculateddate;

@SlingObject
SlingHttpServletRequest slingHttpServletRequest;

@PostConstruct
protected void init() {
if (Objects.nonNull(noofdays)) {
long userEnteredDate = Long.parseLong(noofdays);

LocalDate localStartDate = startdate.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
LocalDate plusDays = localStartDate.plusDays(userEnteredDate);
calculateddate = Date.from(plusDays.atStartOfDay(ZoneId.systemDefault()).toInstant());
Calendar calendar = Calendar.getInstance();
calendar.setTime(calculateddate);

Node currentnode = slingHttpServletRequest.getResource().adaptTo(Node.class);

Session session = slingHttpServletRequest.getResourceResolver().adaptTo(Session.class);
try {
currentnode.setProperty("calculateddate", calendar);
session.save();
} catch (ValueFormatException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (VersionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (LockException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ConstraintViolationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (RepositoryException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

}

}

/**
* @Return the noofdays
*/
public String getNoofdays() {
return noofdays;
}

/**
* @Return the startdate
*/
public Date getStartdate() {
return startdate;
}

}

 

Validating field values on different pages -

DEBAL_DAS_1-1647762442797.png

DEBAL_DAS_2-1647762472310.png

 

Persisted data at component node level -

 

DEBAL_DAS_3-1647762663421.png

 

I feel we could give a try to process the data for completion date field using JS also.