ModeleVerreService.java

package com.sintia.ffl.admin.optique.services.services;

import com.sintia.ffl.admin.optique.dal.entities.Classe;
import com.sintia.ffl.admin.optique.dal.entities.catalogue.ModeleVerreCatalogue;
import com.sintia.ffl.admin.optique.dal.entities.TraitementIntegre;
import com.sintia.ffl.admin.optique.dal.entities.TypeMateriau;
import com.sintia.ffl.admin.optique.dal.entities.TypeVerre;
import com.sintia.ffl.admin.optique.dal.entities.catalogue.VerreTraitIntegresAssoCatalogue;
import com.sintia.ffl.admin.optique.dal.repositories.ClasseRepository;
import com.sintia.ffl.admin.optique.dal.repositories.catalogue.ModeleVerreCatalogueRepository;
import com.sintia.ffl.admin.optique.dal.repositories.TraitementIntegreRepository;
import com.sintia.ffl.admin.optique.dal.repositories.TypeMateriauRepository;
import com.sintia.ffl.admin.optique.dal.repositories.TypeVerreRepository;
import com.sintia.ffl.admin.optique.dal.repositories.catalogue.VerreTraitIntegresAssoCatalogueRepository;
import com.sintia.ffl.admin.optique.services.dto.Glasses;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
@Slf4j
public class ModeleVerreService {

	private final ModeleVerreCatalogueRepository modeleVerreRepository;

	private final ClasseRepository classeRepository;

	private final TypeVerreRepository typeVerreRepository;

	private final TypeMateriauRepository typeMateriauRepository;

	private final TraitementIntegreRepository traitementIntegreRepository;
	
	private final VerreTraitIntegresAssoCatalogueRepository verreTraitIntegresAssoRepository;

	public boolean exist(String maker, String provider, String glassOptoCode) {
		if(maker != null && provider != null && glassOptoCode != null) {
			return modeleVerreRepository.findByCodeOptoVerreAndCodeOptoDistributeurAndCodeOptoFabricant(
					glassOptoCode, provider, maker).isPresent();
		} else return false;
	}

	public void generateTraitIntegresAsso(ModeleVerreCatalogue modeleVerre, String cTraitIntegre, LocalDateTime date) {
		
		Optional<TraitementIntegre> traitementIntegre = traitementIntegreRepository.findBycodeTraitIntegre(cTraitIntegre);
		VerreTraitIntegresAssoCatalogue treatment = new VerreTraitIntegresAssoCatalogue();
		if(traitementIntegre.isPresent()){
			treatment.setIdTraitementIntegre(traitementIntegre.get().getIdTraitIntegre());
			treatment.setDateMaj(date);
			treatment.setCModele(modeleVerre.getCodeModele());
			treatment.setDateCreation(date);
			verreTraitIntegresAssoRepository.save(treatment);
		}
	}
	
	/**
	 * Delete the integrated treatment of a glass.
	 * 
	 * @param modeleVerre the glass which is associated to the treatment
	 * @param traitement the integrated treatment that will be deleted
	 */
	public void deleteVerreTraitementIntegresAsso(ModeleVerreCatalogue modeleVerre, String traitement) {
		
		Optional<TraitementIntegre> traitementIntegre = traitementIntegreRepository.findBycodeTraitIntegre(traitement);
		if(traitementIntegre.isPresent()){
			VerreTraitIntegresAssoCatalogue element = verreTraitIntegresAssoRepository.findBycModeleAndIdTraitementIntegre(modeleVerre.getCodeModele(),
					traitementIntegre.get().getIdTraitIntegre());
			if (element != null) {
				verreTraitIntegresAssoRepository.deleteById(element.getIdVerreTraitIntegresAsso());
				log.info("The treatment '{}' has been removed from the glass {}", traitement, modeleVerre);
			} else {
				log.info(
						"The treatment '{}' hasn't been removed from the glass {}, because it was not associated in the 1st place",
						traitement, modeleVerre);
			}
		}
	}

	/**
	 * TODO As this method is only called from PeremptionVerreItemWriter,
	 * it should be renamed and it should do something like { #expireGlass(GlassesCSV, LocalDateTime)},
	 * ie read the ModeleVerre from the database and update it, instead of re-create it.<br>
	 * <br>
	 * Persist the given glass in the database.<br>
	 * Only the glass entity is persisted, the eventual treatments associated are not updated
	 *
	 * @param glass the glass to persist
	 */
	public void persistGlass(Glasses glass, LocalDateTime updateDate) {
		if (glass != null) {
			// TODO The code started with JDBC in the PeremptionVerreItemReader and ended up using JPA.
			// We should select a unique mode for the whole process.
			ModeleVerreCatalogue mdlVerre = modeleVerreRepository.findByCodeOptoVerreAndCodeOptoDistributeurAndCodeOptoFabricant(
					glass.getGlassOptoCode(), glass.getProvider(), glass.getMaker()).get();
			
			mdlVerre.setDateMaj(updateDate);
			mdlVerre.setDateMajCatalogue(updateDate);
			
			// As the seizable property is changed in the PeremptionVerreItemProcessor, it is also changed here
			mdlVerre.setBSaisie(glass.getSeizable());
			
			modeleVerreRepository.save(mdlVerre);
		} else {
			log.warn("The given glass is null, can't expire it.");
		}
	}

	/**
	 * Return a Glasses from the database, and with the corresponding maker,
	 * provider and glassOptoCode.<br>
	 * If there's no corresponding glasses in the database, return null
	 *
	 * @param maker
	 * @param provider
	 * @param glassOptoCode
	 * @return
	 */
	public Glasses findVerreById(String maker, String provider, String glassOptoCode) {
		Glasses result = null;

		Optional<ModeleVerreCatalogue> opt = modeleVerreRepository.findByCodeOptoVerreAndCodeOptoDistributeurAndCodeOptoFabricant(
				glassOptoCode, provider, maker);
		if (opt.isPresent()) {
			ModeleVerreCatalogue entity = opt.get();
			result = new Glasses();
			
			result.setGlassCode(entity.getCodeModele());

			result.setGlassClass(this.classeRepository.findById(entity.getIdClasse()).map(Classe::getCode).orElse(null));
			result.setGlassName(entity.getLModele());
			result.setGlassType(this.typeVerreRepository.findById(entity.getIdTypeVerre()).map(TypeVerre::getCTypeVerre).orElse(null));
			result.setMaterial(this.typeMateriauRepository.findById(entity.getIdTypeMateriau()).map(TypeMateriau::getCTypeMateriau).orElse(null));
			result.setRefractiveIndex(entity.getNIndice());
			
			List<VerreTraitIntegresAssoCatalogue> verreTraitIntegresAssos = verreTraitIntegresAssoRepository.findBycModele(entity.getCodeModele());
			if (!verreTraitIntegresAssos.isEmpty()) {
				result.setTreatments(
						verreTraitIntegresAssos.stream()
								.map(
										v -> this.traitementIntegreRepository.findById(v.getIdTraitementIntegre())
												.map(TraitementIntegre::getCodeTraitIntegre)
												.orElse(null)
								)
								.collect(Collectors.toList())
				);
			} else {
				result.setTreatments(Collections.emptyList());
			}
			
			if (null != entity.getDateDemandeSupp()) {
				result.setExpiryDate(entity.getDateDemandeSupp());
			} else {
				result.setExpiryDate(null);
			}

			
			result.setRefractiveIndex(entity.getNIndice());

		}
		return result;
	}

	public boolean hasSurfaceType(Glasses glasses) {
		return hasAttribute(glasses, "AS");
	}

	public boolean isHardened(Glasses glasses) {
		return hasAttribute(glasses, "DU");
	}

	public boolean isAntiReflection(Glasses glasses) {
		return hasAttribute(glasses, "SAR");
	}

	public boolean isPhotochromic(Glasses glasses) {
		return hasAttribute(glasses, "PR");
	}

	public boolean isTinted(Glasses glasses) {
		return hasAttribute(glasses, "CO");
	}

	private boolean hasAttribute(Glasses glasses, String attribute) {
		return glasses != null && glasses.getTreatments() != null && glasses.getTreatments().contains(attribute);
	}

}