Completion date calculated based on a start date and an amount from a number field. | Community
Skip to main content
nowackem
Level 5
March 18, 2022
Solved

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

  • March 18, 2022
  • 1 reply
  • 1070 views

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!

This post is no longer active and is closed to new replies. Need help? Start a new post to ask your question.
Best answer by DEBAL_DAS

I am sharing one sample implementation hope this will help -

 

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

 

 

.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();
}

}

}

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

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

}

 

Validating field values on different pages -

 

Persisted data at component node level -

 

 

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

1 reply

DEBAL_DAS
DEBAL_DASAccepted solution
New Member
March 20, 2022

I am sharing one sample implementation hope this will help -

 

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

 

 

.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();
}

}

}

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

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

}

 

Validating field values on different pages -

 

Persisted data at component node level -

 

 

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

Debal Das, Senior AEM Consultant
nowackem
nowackemAuthor
Level 5
March 21, 2022

Thank you so much!