424 lines
22 KiB
Java
424 lines
22 KiB
Java
package com.utopiaindustries.service;
|
|
|
|
|
|
import com.utopiaindustries.dao.ctp.*;
|
|
import com.utopiaindustries.model.ctp.*;
|
|
import com.utopiaindustries.util.CTPDateTimeFormat;
|
|
import com.utopiaindustries.util.StringUtils;
|
|
import org.springframework.stereotype.Service;
|
|
|
|
import java.math.BigDecimal;
|
|
import java.math.RoundingMode;
|
|
import java.time.Duration;
|
|
import java.time.LocalDate;
|
|
import java.time.LocalDateTime;
|
|
import java.time.format.DateTimeFormatter;
|
|
import java.util.*;
|
|
import java.util.function.Function;
|
|
import java.util.stream.Collectors;
|
|
|
|
@Service
|
|
public class ReportingService {
|
|
|
|
private final JobCardItemDAO jobCardItemDAO;
|
|
private final CutPieceDAO cutPieceDAO;
|
|
private final BundleDAO bundleDAO;
|
|
private final InventoryTransactionLegDAO inventoryTransactionLegDAO;
|
|
private final InventoryTransactionDAO inventoryTransactionDAO;
|
|
private final JobCardDAO jobCardDAO;
|
|
private final CryptographyService cryptographyService;
|
|
private final MasterBundleDAO masterBundleDAO;
|
|
private final FinishedItemDAO finishedItemDAO;
|
|
private final StitchingOfflineItemDAO stitchingOfflineItemDAO;
|
|
private final InventoryAccountDAO inventoryAccountDAO;
|
|
|
|
public ReportingService( JobCardItemDAO jobCardItemDAO, CutPieceDAO cutPieceDAO, BundleDAO bundleDAO, InventoryTransactionLegDAO inventoryTransactionLegDAO, InventoryTransactionDAO inventoryTransactionDAO, JobCardDAO jobCardDAO, CryptographyService cryptographyService, MasterBundleDAO masterBundleDAO, FinishedItemDAO finishedItemDAO, StitchingOfflineItemDAO stitchingOfflineItemDAO, InventoryAccountDAO inventoryAccountDAO) {
|
|
this.jobCardItemDAO = jobCardItemDAO;
|
|
this.cutPieceDAO = cutPieceDAO;
|
|
this.bundleDAO = bundleDAO;
|
|
this.inventoryTransactionLegDAO = inventoryTransactionLegDAO;
|
|
this.inventoryTransactionDAO = inventoryTransactionDAO;
|
|
this.jobCardDAO = jobCardDAO;
|
|
this.cryptographyService = cryptographyService;
|
|
this.masterBundleDAO = masterBundleDAO;
|
|
this.finishedItemDAO = finishedItemDAO;
|
|
this.stitchingOfflineItemDAO = stitchingOfflineItemDAO;
|
|
this.inventoryAccountDAO = inventoryAccountDAO;
|
|
}
|
|
|
|
public Map<String,Integer> getJobCardProgress(String jobCardID){
|
|
if (jobCardID == null){
|
|
return new HashMap<>();
|
|
}else {
|
|
HashMap<String,Integer> totalProgress = new HashMap<>();
|
|
List<JobCardItem> jobCardItems = jobCardItemDAO.findByCardId(Long.parseLong(jobCardID));
|
|
BigDecimal totalProduction = jobCardItems.stream()
|
|
.map(item -> Optional.ofNullable(item.getTotalProduction()).orElse(BigDecimal.ZERO))
|
|
.reduce(BigDecimal.ZERO, BigDecimal::add);
|
|
|
|
BigDecimal actualProduction = jobCardItems.stream()
|
|
.map(item -> Optional.ofNullable(item.getActualProduction()).orElse(BigDecimal.ZERO))
|
|
.reduce(BigDecimal.ZERO, BigDecimal::add);
|
|
|
|
BigDecimal expectedProduction = jobCardItems.stream()
|
|
.map(item -> Optional.ofNullable(item.getExpectedProduction()).orElse(BigDecimal.ZERO))
|
|
.reduce(BigDecimal.ZERO, BigDecimal::add);
|
|
|
|
if (actualProduction.compareTo(BigDecimal.ZERO) == 0 ) {
|
|
totalProgress.put("Cutting Progress", BigDecimal.ZERO.intValue());
|
|
|
|
} else if (actualProduction.compareTo(expectedProduction) < 0) {
|
|
BigDecimal cuttingProgress = expectedProduction
|
|
.divide(actualProduction, 4, BigDecimal.ROUND_HALF_UP)
|
|
.multiply(BigDecimal.valueOf(100));
|
|
totalProgress.put("Cutting Progress", cuttingProgress.intValue());
|
|
}else if (actualProduction.compareTo(expectedProduction) > 0 || actualProduction.compareTo(expectedProduction) == 0){
|
|
totalProgress.put("Cutting Progress", 100);
|
|
}
|
|
|
|
if (totalProduction.compareTo(BigDecimal.ZERO) == 0){
|
|
totalProgress.put("Stitching Progress", BigDecimal.ZERO.intValue());
|
|
}else {
|
|
BigDecimal stitchingProgress = totalProduction
|
|
.divide(actualProduction, 4, BigDecimal.ROUND_HALF_UP)
|
|
.multiply(BigDecimal.valueOf(100));
|
|
totalProgress.put("Stitching Progress", stitchingProgress.intValue());
|
|
}
|
|
Long qaProgressItems = stitchingOfflineItemDAO.CalculateTotalQA(Long.parseLong(jobCardID));
|
|
if (qaProgressItems == 0){
|
|
totalProgress.put("QA Progress", 0);
|
|
}else {
|
|
BigDecimal qaProgress = BigDecimal.valueOf(qaProgressItems)
|
|
.divide(actualProduction, 4, BigDecimal.ROUND_HALF_UP)
|
|
.multiply(BigDecimal.valueOf(100));
|
|
totalProgress.put("QA Progress", qaProgress.intValue());
|
|
}
|
|
Long totalFinishItem = finishedItemDAO.calculateTotalFinishItem(Long.parseLong(jobCardID));
|
|
if (totalFinishItem == 0){
|
|
totalProgress.put("Finishing Progress", BigDecimal.ZERO.intValue());
|
|
}else {
|
|
BigDecimal finishItemProgress = BigDecimal.valueOf(totalFinishItem)
|
|
.divide(actualProduction, 4, BigDecimal.ROUND_HALF_UP)
|
|
.multiply(BigDecimal.valueOf(100));
|
|
totalProgress.put("Finishing Progress", finishItemProgress.intValue());
|
|
}
|
|
|
|
if (totalProduction.compareTo(BigDecimal.ZERO) == 0 && actualProduction.compareTo(BigDecimal.ZERO) == 0 ) {
|
|
totalProgress.put("Job Card Progress", BigDecimal.ZERO.intValue());
|
|
} else {
|
|
if (actualProduction.compareTo(expectedProduction)>0){
|
|
BigDecimal progressPercentage = actualProduction.add(totalProduction).add(BigDecimal.valueOf(qaProgressItems)).add(BigDecimal.valueOf(totalFinishItem))
|
|
.divide(actualProduction.multiply(BigDecimal.valueOf(4)), 4, RoundingMode.HALF_UP)
|
|
.multiply(BigDecimal.valueOf(100));
|
|
totalProgress.put("Job Card Progress", progressPercentage.intValue());
|
|
}else {
|
|
BigDecimal progressPercentage = actualProduction.add(totalProduction).add(BigDecimal.valueOf(qaProgressItems)).add(BigDecimal.valueOf(totalFinishItem))
|
|
.divide(expectedProduction.multiply(BigDecimal.valueOf(4)), 4, RoundingMode.HALF_UP)
|
|
.multiply(BigDecimal.valueOf(100));
|
|
totalProgress.put("Job Card Progress", progressPercentage.intValue());
|
|
}
|
|
}
|
|
return totalProgress;
|
|
}
|
|
}
|
|
|
|
public Integer getTotalProduction(String jobCardID){
|
|
if (jobCardID == null){
|
|
return 0;
|
|
}else {
|
|
List<JobCardItem> jobCardItems = jobCardItemDAO.findByCardId(Long.parseLong(jobCardID));
|
|
BigDecimal actualProduction = jobCardItems.stream()
|
|
.map(item -> Optional.ofNullable(item.getActualProduction()).orElse(BigDecimal.ZERO))
|
|
.reduce(BigDecimal.ZERO, BigDecimal::add);
|
|
|
|
return actualProduction.intValue();
|
|
}
|
|
}
|
|
|
|
public Map<String,Integer> getCompleteProduction(String jobCardID){
|
|
if (jobCardID == null){
|
|
return new HashMap<>();
|
|
}else {
|
|
HashMap<String,Integer> totalProgress = new HashMap<>();
|
|
List<JobCardItem> jobCardItems = jobCardItemDAO.findByCardId(Long.parseLong(jobCardID));
|
|
BigDecimal totalProduction = jobCardItems.stream()
|
|
.map(item -> Optional.ofNullable(item.getTotalProduction()).orElse(BigDecimal.ZERO))
|
|
.reduce(BigDecimal.ZERO, BigDecimal::add);
|
|
|
|
BigDecimal actualProduction = jobCardItems.stream()
|
|
.map(item -> Optional.ofNullable(item.getActualProduction()).orElse(BigDecimal.ZERO))
|
|
.reduce(BigDecimal.ZERO, BigDecimal::add);
|
|
|
|
BigDecimal expectedProduction = jobCardItems.stream()
|
|
.map(item -> Optional.ofNullable(item.getExpectedProduction()).orElse(BigDecimal.ZERO))
|
|
.reduce(BigDecimal.ZERO, BigDecimal::add);
|
|
|
|
Long qaProgressItems = stitchingOfflineItemDAO.CalculateTotalQA(Long.parseLong(jobCardID));
|
|
Long totalFinishItem = finishedItemDAO.calculateTotalFinishItem(Long.parseLong(jobCardID));
|
|
|
|
totalProgress.put("Cutting Progress", actualProduction.intValue());
|
|
totalProgress.put("Stitching Progress", totalProduction.intValue());
|
|
totalProgress.put("QA Progress", qaProgressItems.intValue());
|
|
totalProgress.put("Finishing Progress", totalFinishItem.intValue());
|
|
|
|
return totalProgress;
|
|
}
|
|
}
|
|
|
|
public Map<String,Integer> getSegregateItems(String jobCardID){
|
|
if (jobCardID == null){
|
|
return new HashMap<>();
|
|
}else {
|
|
HashMap<String,Integer> gradingItems = new HashMap<>();
|
|
List<InventoryAccount> inventoryAccounts = inventoryAccountDAO.getPackagingAccounts();
|
|
List<FinishedItem> finishedItems = finishedItemDAO.findByJobCardId(Long.parseLong(jobCardID));
|
|
List<Long> finishItemsIds = finishedItems.stream()
|
|
.map(FinishedItem::getId).collect(Collectors.toList());
|
|
if (finishItemsIds.isEmpty()){
|
|
return gradingItems;
|
|
}else {
|
|
for (InventoryAccount inventoryAccount : inventoryAccounts){
|
|
long totalGradingItems = inventoryTransactionLegDAO.CalculateTotalGradingItems(finishItemsIds,(int) inventoryAccount.getId());
|
|
gradingItems.put(inventoryAccount.getTitle(), (int) totalGradingItems);
|
|
}
|
|
return gradingItems;
|
|
}
|
|
}
|
|
}
|
|
|
|
public HashMap<String,String> getEachPhaseTotalTime(String jobCardID){
|
|
if (jobCardID == null){
|
|
return new HashMap<>();
|
|
}else {
|
|
HashMap<String,String> phasesTimes = new HashMap<>();
|
|
JobCard jobCard = jobCardDAO.find(Long.parseLong(jobCardID));
|
|
Bundle lastBundle = bundleDAO.findLastBundleByCardId(Long.parseLong(jobCardID));
|
|
|
|
//Cutting time
|
|
StringBuilder cuttingTime = generateTime(jobCard.getCreatedAt(),lastBundle.getCreatedAt());
|
|
phasesTimes.put("Cutting Total Time",cuttingTime.toString());
|
|
|
|
//Stitching time
|
|
List<Long> bundlesIds = bundleDAO.findByCardId(Long.parseLong(jobCardID)).stream().map(Bundle::getId).collect(Collectors.toList());
|
|
if (!bundlesIds.isEmpty()){
|
|
InventoryTransactionLeg inventoryTransactionLeg = inventoryTransactionLegDAO.getFirstStitchBundleTime(bundlesIds,"STITCH_BUNDLE");
|
|
StitchingOfflineItem lastStitchItem = stitchingOfflineItemDAO.getLastStitchItemByCardIdAndTime(Long.parseLong(jobCardID));
|
|
StringBuilder stitchingTime = generateTime(inventoryTransactionLeg.getTransactionLegDateTime(),lastStitchItem.getCreatedAt());
|
|
phasesTimes.put("Stitching Total Time",stitchingTime.toString());
|
|
}else {
|
|
phasesTimes.put("Stitching Total Time",null);
|
|
|
|
}
|
|
|
|
return phasesTimes;
|
|
}
|
|
}
|
|
|
|
public HashMap<String,String> countPendingItemsOnDifferentPhases(String jobCardID){
|
|
if (jobCardID == null){
|
|
return new HashMap<>();
|
|
}else {
|
|
HashMap<String,String> phasePending = new HashMap<String,String>();
|
|
List<JobCardItem> jobCardItems = jobCardItemDAO.findByCardId(Long.parseLong(jobCardID));
|
|
BigDecimal totalProduction = jobCardItems.stream()
|
|
.map(item -> Optional.ofNullable(item.getTotalProduction()).orElse(BigDecimal.ZERO))
|
|
.reduce(BigDecimal.ZERO, BigDecimal::add);
|
|
|
|
BigDecimal actualProduction = jobCardItems.stream()
|
|
.map(item -> Optional.ofNullable(item.getActualProduction()).orElse(BigDecimal.ZERO))
|
|
.reduce(BigDecimal.ZERO, BigDecimal::add);
|
|
|
|
BigDecimal expectedProduction = jobCardItems.stream()
|
|
.map(item -> Optional.ofNullable(item.getExpectedProduction()).orElse(BigDecimal.ZERO))
|
|
.reduce(BigDecimal.ZERO, BigDecimal::add);
|
|
if(actualProduction.compareTo(totalProduction) == 0) {
|
|
phasePending.put("Stitching Total Time", null);
|
|
}else {
|
|
phasePending.put("Stitching Total Time", "Pending");
|
|
}
|
|
return phasePending;
|
|
}
|
|
}
|
|
|
|
public Map<String, Map<String, Object>> getCuttingDetails(String jobCardID) {
|
|
if (jobCardID == null) {
|
|
return Collections.emptyMap();
|
|
}
|
|
|
|
Map<String, Map<String, Object>> cuttingDetails = new HashMap<>();
|
|
Map<String, InventoryAccount> cuttingAccount = new HashMap<>();
|
|
Map<String, String> cuttingPersonName = new HashMap<>();
|
|
Map<String, LocalDate> cuttingDate = new HashMap<>();
|
|
|
|
List<Bundle> bundles = bundleDAO.findByCardId(Long.parseLong(jobCardID));
|
|
if (bundles.isEmpty()) {
|
|
return cuttingDetails;
|
|
}
|
|
|
|
Map<Long, Bundle> bundleMap = bundles.stream()
|
|
.collect(Collectors.toMap(Bundle::getId, Function.identity()));
|
|
|
|
List<Long> bundleIds = new ArrayList<>(bundleMap.keySet());
|
|
List<InventoryTransactionLeg> inventoryTransactionLegs = inventoryTransactionLegDAO
|
|
.getTransactionByParentIdAndType(bundleIds, "BUNDLE");
|
|
|
|
for (InventoryTransactionLeg inventoryTransactionLeg : inventoryTransactionLegs) {
|
|
Integer accountId = inventoryTransactionLeg.getAccountId();
|
|
InventoryAccount inventoryAccount = inventoryAccountDAO.find(accountId.longValue());
|
|
if (inventoryAccount != null) {
|
|
String accountTitle = inventoryAccount.getTitle();
|
|
cuttingAccount.put(accountTitle, inventoryAccount);
|
|
Bundle bundle = bundleMap.get(inventoryTransactionLeg.getParentDocumentId());
|
|
cuttingPersonName.put(accountTitle, (bundle != null) ? bundle.getCreatedBy() : null);
|
|
cuttingDate.put(accountTitle,(bundle != null) ? bundle.getCreatedAt().toLocalDate() : null);
|
|
}
|
|
}
|
|
|
|
cuttingDetails.put("accounts", new HashMap<>(cuttingAccount));
|
|
cuttingDetails.put("personName", new HashMap<>(cuttingPersonName));
|
|
cuttingDetails.put("date", new HashMap<>(cuttingDate));
|
|
|
|
return cuttingDetails;
|
|
}
|
|
|
|
public Map<String, Map<String, Object>> getStitchingDetails(String jobCardID) {
|
|
if (jobCardID == null) {
|
|
return Collections.emptyMap();
|
|
}
|
|
|
|
Map<String, Map<String, Object>> stitchingDetails = new HashMap<>();
|
|
Map<String, InventoryAccount> stitchingAccount = new HashMap<>();
|
|
Map<String, String> stitchingPersonName = new HashMap<>();
|
|
Map<String, LocalDate> stitchingDate = new HashMap<>();
|
|
|
|
List<StitchingOfflineItem> stitchingOfflineItems = stitchingOfflineItemDAO.findByJobCardId(Long.parseLong(jobCardID));
|
|
if (stitchingOfflineItems.isEmpty()) {
|
|
return stitchingDetails;
|
|
}
|
|
|
|
Map<Long, StitchingOfflineItem> stitchingOfflineItemMap = stitchingOfflineItems.stream()
|
|
.collect(Collectors.toMap(StitchingOfflineItem::getId, Function.identity()));
|
|
|
|
List<Long> stitchingItemsArray = new ArrayList<>(stitchingOfflineItemMap.keySet());
|
|
List<InventoryTransactionLeg> inventoryTransactionLegs = inventoryTransactionLegDAO
|
|
.getTransactionByParentIdAndType(stitchingItemsArray, "STITCHING_OFFLINE");
|
|
|
|
for (InventoryTransactionLeg inventoryTransactionLeg : inventoryTransactionLegs) {
|
|
Integer accountId = inventoryTransactionLeg.getAccountId();
|
|
InventoryAccount inventoryAccount = inventoryAccountDAO.find(accountId.longValue());
|
|
if (inventoryAccount != null) {
|
|
String accountTitle = inventoryAccount.getTitle();
|
|
stitchingAccount.put(accountTitle, inventoryAccount);
|
|
StitchingOfflineItem stitchingOfflineItem = stitchingOfflineItemMap.get(inventoryTransactionLeg.getParentDocumentId());
|
|
stitchingPersonName.put(accountTitle, (stitchingOfflineItem != null) ? stitchingOfflineItem.getCreatedBy() : null);
|
|
stitchingDate.put(accountTitle,(stitchingOfflineItem != null) ? stitchingOfflineItem.getCreatedAt().toLocalDate() : null);
|
|
}
|
|
}
|
|
|
|
stitchingDetails.put("accounts", new HashMap<>(stitchingAccount));
|
|
stitchingDetails.put("personName", new HashMap<>(stitchingPersonName));
|
|
stitchingDetails.put("date", new HashMap<>(stitchingDate));
|
|
|
|
return stitchingDetails;
|
|
}
|
|
|
|
|
|
public Map<String, List<?>> getPhasesProgressDayWise(String jobCardID) {
|
|
if (jobCardID == null) {
|
|
return Collections.emptyMap();
|
|
}
|
|
List<JobCardItem> jobCardItems = jobCardItemDAO.findByCardId(Long.parseLong(jobCardID));
|
|
BigDecimal actualProduction = jobCardItems.stream()
|
|
.map(item -> Optional.ofNullable(item.getActualProduction()).orElse(BigDecimal.ZERO))
|
|
.reduce(BigDecimal.ZERO, BigDecimal::add);
|
|
|
|
LocalDateTime startDate = jobCardDAO.find(Long.parseLong(jobCardID)).getCreatedAt();
|
|
HashMap<String, List<?>> barChartData = new HashMap<>();
|
|
|
|
List<InventoryTransactionLeg> inventoryTransactionLegs = inventoryTransactionLegDAO
|
|
.getTransactionByJobCardAndDatesAndType(Long.parseLong(jobCardID), startDate.toString(), LocalDateTime.now().toString(), "IN");
|
|
|
|
//remove quality multiple transaction entry approved/rejects
|
|
List<InventoryTransactionLeg> filteredTransactions = inventoryTransactionLegs.stream()
|
|
.collect(Collectors.toMap(
|
|
leg -> leg.getAccountId() + "-" + leg.getParentDocumentType() + "-" + leg.getParentDocumentId(),
|
|
leg -> leg, // Value
|
|
(existing, replacement) -> existing.getTransactionLegDateTime().isBefore(replacement.getTransactionLegDateTime()) ? existing : replacement // Keep Oldest
|
|
))
|
|
.values()
|
|
.stream()
|
|
.collect(Collectors.toList());
|
|
|
|
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
|
|
|
|
List<String> uniqueDates = inventoryTransactionLegs.stream()
|
|
.map(leg -> leg.getTransactionLegDateTime().toLocalDate().format(formatter))
|
|
.distinct()
|
|
.sorted()
|
|
.collect(Collectors.toList());
|
|
|
|
Map<String, Integer> dateIndexMap = new HashMap<>();
|
|
for (int i = 0; i < uniqueDates.size(); i++) {
|
|
dateIndexMap.put(uniqueDates.get(i), i);
|
|
}
|
|
|
|
List<Integer> cuttingList = new ArrayList<>(Collections.nCopies(uniqueDates.size(), 0));
|
|
List<Integer> stitchingList = new ArrayList<>(Collections.nCopies(uniqueDates.size(), 0));
|
|
List<Integer> qualityList = new ArrayList<>(Collections.nCopies(uniqueDates.size(), 0));
|
|
List<Integer> finishItems = new ArrayList<>(Collections.nCopies(uniqueDates.size(), 0));
|
|
|
|
for (InventoryTransactionLeg leg : filteredTransactions) {
|
|
String dateKey = leg.getTransactionLegDateTime().format(formatter);
|
|
int index = dateIndexMap.get(dateKey);
|
|
if ("BUNDLE".equals(leg.getParentDocumentType())) {
|
|
Bundle bundle = bundleDAO.find(leg.getParentDocumentId());
|
|
cuttingList.set(index, cuttingList.get(index) + bundle.getWrapQuantity().intValue());
|
|
}
|
|
else if ("STITCHING_OFFLINE".equals(leg.getParentDocumentType())) {
|
|
stitchingList.set(index, stitchingList.get(index) + leg.getQuantity().intValue());
|
|
}
|
|
else if ("FINISHED_ITEM".equals(leg.getParentDocumentType()) && (leg.getAccountId().equals(7) || leg.getAccountId().equals(12))) {
|
|
if (index == 0 || !dateIndexMap.containsKey(dateKey)) {
|
|
qualityList.set(index, 0);
|
|
}
|
|
qualityList.set(index, qualityList.get(index) + leg.getQuantity().intValue());
|
|
}else if ("FINISHED_ITEM".equals(leg.getParentDocumentType()) && (leg.getAccountId().equals(8) || leg.getAccountId().equals(9) || leg.getAccountId().equals(10))) {
|
|
if (index == 0 || !dateIndexMap.containsKey(dateKey)) {
|
|
finishItems.set(index, 0);
|
|
}
|
|
finishItems.set(index, finishItems.get(index) + leg.getQuantity().intValue());
|
|
}
|
|
}
|
|
|
|
barChartData.put("dates", uniqueDates);
|
|
barChartData.put("cutting", cuttingList);
|
|
barChartData.put("stitching", stitchingList);
|
|
barChartData.put("quality", qualityList);
|
|
barChartData.put("finishing", finishItems);
|
|
|
|
return barChartData;
|
|
}
|
|
|
|
|
|
|
|
private StringBuilder generateTime(LocalDateTime startDate, LocalDateTime endDate){
|
|
StringBuilder totalTime = new StringBuilder();
|
|
if(startDate != null && endDate != null){
|
|
Duration duration = Duration.between(startDate, endDate);
|
|
if (duration.toDays() > 0) {
|
|
totalTime.append(String.format("%d days, ", duration.toDays()));
|
|
}
|
|
|
|
if (duration.toHours() % 24 > 0) {
|
|
totalTime.append(String.format("%d hours, ", duration.toHours() % 24));
|
|
}
|
|
|
|
if (duration.toMinutes() % 60 > 0) {
|
|
totalTime.append(String.format("%d minutes ", duration.toMinutes() % 60));
|
|
}
|
|
return totalTime;
|
|
}else return totalTime.append("");
|
|
}
|
|
|
|
}
|