Your achievements

Level 1

0% to

Level 2

Tip /
Sign in

Sign in to Community

to gain points, level up, and earn exciting badges like the new
Bedrock Mission!

Learn more

View all

Sign in to view all badges

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
Community 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
Community 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.