Commit 07ae3835 authored by PECQUOT's avatar PECQUOT Committed by PECQUOT
Browse files

[enh] Add ExpectedSale (Model, Repository, Service...)

[enh] Add Batch.subgroupCount
parent 3ca75b9d
......@@ -22,9 +22,7 @@ package net.sumaris.core.dao.data;
* #L%
*/
import net.sumaris.core.model.data.BatchSortingMeasurement;
import net.sumaris.core.model.data.IDataEntity;
import net.sumaris.core.dao.technical.model.IEntity;
import net.sumaris.core.model.data.IMeasurementEntity;
import net.sumaris.core.vo.data.MeasurementVO;
import net.sumaris.core.vo.data.QuantificationMeasurementVO;
......@@ -42,7 +40,7 @@ public interface MeasurementDao {
Class<? extends IMeasurementEntity> entityClass,
List<V> sources,
List<T> target,
IDataEntity<?> parent);
IEntity<?> parent);
<T extends IMeasurementEntity> List<T> getMeasurementEntitiesByParentId(Class<T> entityClass,
String parentPropertyName,
......@@ -96,6 +94,12 @@ public interface MeasurementDao {
List<MeasurementVO> saveSaleMeasurements(int saleId, List<MeasurementVO> sources);
Map<Integer, String> saveSaleMeasurementsMap(int saleId, Map<Integer, String> sources);
// Expected Sale
List<MeasurementVO> getExpectedSaleMeasurements(int saleId);
Map<Integer, String> getExpectedSaleMeasurementsMap(int saleId);
List<MeasurementVO> saveExpectedSaleMeasurements(int saleId, List<MeasurementVO> sources);
Map<Integer, String> saveExpectedSaleMeasurementsMap(int saleId, Map<Integer, String> sources);
// Landing
List<MeasurementVO> saveLandingMeasurements(int landingId, List<MeasurementVO> sources);
Map<Integer, String> saveLandingMeasurementsMap(final int landingId, Map<Integer, String> sources);
......
......@@ -344,6 +344,25 @@ public class MeasurementDaoImpl extends HibernateDaoSupport implements Measureme
);
}
@Override
public List<MeasurementVO> getExpectedSaleMeasurements(int saleId) {
return getMeasurementsByParentId(SaleMeasurement.class,
MeasurementVO.class,
SaleMeasurement.Fields.EXPECTED_SALE,
saleId,
SaleMeasurement.Fields.ID
);
}
@Override
public Map<Integer, String> getExpectedSaleMeasurementsMap(int saleId) {
return getMeasurementsMapByParentId(SaleMeasurement.class,
SaleMeasurement.Fields.EXPECTED_SALE,
saleId,
null
);
}
@Override
public <T extends IMeasurementEntity, V extends MeasurementVO> V toMeasurementVO(T source, Class<? extends V> voClass) {
if (source == null) return null;
......@@ -452,6 +471,18 @@ public class MeasurementDaoImpl extends HibernateDaoSupport implements Measureme
return saveMeasurementsMap(SaleMeasurement.class, sources, parent.getMeasurements(), parent);
}
@Override
public List<MeasurementVO> saveExpectedSaleMeasurements(int saleId, List<MeasurementVO> sources) {
ExpectedSale parent = getById(ExpectedSale.class, saleId);
return saveMeasurements(SaleMeasurement.class, sources, parent.getMeasurements(), parent);
}
@Override
public Map<Integer, String> saveExpectedSaleMeasurementsMap(int saleId, Map<Integer, String> sources) {
ExpectedSale parent = getById(ExpectedSale.class, saleId);
return saveMeasurementsMap(SaleMeasurement.class, sources, parent.getMeasurements(), parent);
}
@Override
public List<MeasurementVO> saveLandingMeasurements(final int landingId, List<MeasurementVO> sources) {
Landing parent = getById(Landing.class, landingId);
......@@ -603,7 +634,7 @@ public class MeasurementDaoImpl extends HibernateDaoSupport implements Measureme
final Class<? extends IMeasurementEntity> entityClass,
List<V> sources,
List<T> target,
final IDataEntity<?> parent) {
final IEntity<?> parent) {
final EntityManager em = getEntityManager();
......@@ -717,7 +748,7 @@ public class MeasurementDaoImpl extends HibernateDaoSupport implements Measureme
}
@SuppressWarnings("unchecked")
protected <T extends IDataEntity<?>> Class<T> getEntityClass(T source) {
protected <T extends IEntity<?>> Class<T> getEntityClass(T source) {
String classname = source.getClass().getName();
int index = classname.indexOf("$HibernateProxy");
if (index > 0) {
......@@ -736,7 +767,7 @@ public class MeasurementDaoImpl extends HibernateDaoSupport implements Measureme
final Class<? extends T> entityClass,
Map<Integer, String> sources,
List<T> target,
final IDataEntity<?> parent) {
final IEntity<?> parent) {
final EntityManager session = getEntityManager();
......@@ -1009,15 +1040,17 @@ public class MeasurementDaoImpl extends HibernateDaoSupport implements Measureme
}
}
protected void fillDefaultProperties(IDataEntity<?> parent, IMeasurementEntity target) {
protected void fillDefaultProperties(IEntity<?> parent, IMeasurementEntity target) {
// Recorder department
if (target.getRecorderDepartment() == null) {
if (parent.getRecorderDepartment() == null || parent.getRecorderDepartment().getId() == null) {
target.setRecorderDepartment(null);
}
else {
target.setRecorderDepartment(parent.getRecorderDepartment());
if (parent instanceof IDataEntity) {
IDataEntity<?> parentData = (IDataEntity<?>) parent;
// Recorder department
if (target.getRecorderDepartment() == null) {
if (parentData.getRecorderDepartment() == null || parentData.getRecorderDepartment().getId() == null) {
target.setRecorderDepartment(null);
} else {
target.setRecorderDepartment(parentData.getRecorderDepartment());
}
}
}
......
......@@ -25,7 +25,6 @@ package net.sumaris.core.dao.data.fishingArea;
import net.sumaris.core.dao.technical.jpa.BindableSpecification;
import net.sumaris.core.dao.technical.jpa.SumarisJpaRepository;
import net.sumaris.core.dao.technical.model.IEntity;
import net.sumaris.core.model.data.Batch;
import net.sumaris.core.model.data.FishingArea;
import net.sumaris.core.vo.data.FishingAreaVO;
import org.springframework.data.jpa.domain.Specification;
......@@ -54,7 +53,7 @@ public interface FishingAreaRepository
}
List<FishingArea> getAllByOperationId(int operationId);
List<FishingArea> getFishingAreaByOperationId(int operationId);
Set<Integer> getAllIdsByOperationId(int operationId);
......
......@@ -154,8 +154,8 @@ public class FishingAreaRepositoryImpl
}
@Override
public List<FishingAreaVO> getAllVOByOperationId(int operationId) {
return self.getAllByOperationId(operationId).stream()
public List<FishingAreaVO> getAllByOperationId(int operationId) {
return self.getFishingAreaByOperationId(operationId).stream()
.map(this::toVO).collect(Collectors.toList());
}
......
......@@ -30,7 +30,7 @@ import java.util.List;
public interface FishingAreaSpecifications {
List<FishingAreaVO> getAllVOByOperationId(int operationId);
List<FishingAreaVO> getAllByOperationId(int operationId);
List<FishingAreaVO> saveAllByOperationId(int operationId, List<FishingAreaVO> fishingAreas);
......
......@@ -143,7 +143,7 @@ public class OperationGroupRepositoryImpl
target.setProducts(productRepository.findAll(ProductFilterVO.builder().operationId(operationId).build()));
// Fishing Areas
target.setFishingAreas(fishingAreaRepository.getAllVOByOperationId(operationId));
target.setFishingAreas(fishingAreaRepository.getAllByOperationId(operationId));
// Packets
// TODO
......
package net.sumaris.core.dao.data.sale;
/*-
* #%L
* SUMARiS:: Core
* %%
* Copyright (C) 2018 - 2020 SUMARiS Consortium
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this program. If not, see
* <http://www.gnu.org/licenses/gpl-3.0.html>.
* #L%
*/
import net.sumaris.core.dao.technical.jpa.SumarisJpaRepository;
import net.sumaris.core.model.data.ExpectedSale;
import net.sumaris.core.vo.data.ExpectedSaleVO;
import java.util.List;
import java.util.Set;
/**
* @author peck7 on 01/09/2020.
*/
public interface ExpectedSaleRepository
extends SumarisJpaRepository<ExpectedSale, Integer, ExpectedSaleVO>, ExpectedSaleSpecifications {
List<ExpectedSale> getExpectedSaleByTripId(int tripId);
Set<Integer> getAllIdsByTripId(int tripId);
}
package net.sumaris.core.dao.data.sale;
import net.sumaris.core.dao.referential.ReferentialDao;
import net.sumaris.core.dao.referential.location.LocationRepository;
import net.sumaris.core.dao.technical.jpa.SumarisJpaRepositoryImpl;
import net.sumaris.core.model.data.ExpectedSale;
import net.sumaris.core.model.data.Landing;
import net.sumaris.core.model.data.Trip;
import net.sumaris.core.model.referential.SaleType;
import net.sumaris.core.model.referential.location.Location;
import net.sumaris.core.vo.data.ExpectedSaleVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import javax.persistence.EntityManager;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
public class ExpectedSaleRepositoryImpl
extends SumarisJpaRepositoryImpl<ExpectedSale, Integer, ExpectedSaleVO>
implements ExpectedSaleSpecifications {
private final LocationRepository locationRepository;
private final ReferentialDao referentialDao;
@Autowired
@Lazy
private ExpectedSaleRepository self;
@Autowired
protected ExpectedSaleRepositoryImpl(EntityManager entityManager, LocationRepository locationRepository, ReferentialDao referentialDao) {
super(ExpectedSale.class, ExpectedSaleVO.class, entityManager);
this.locationRepository = locationRepository;
this.referentialDao = referentialDao;
}
@Override
public void toVO(ExpectedSale source, ExpectedSaleVO target, boolean copyIfNull) {
super.toVO(source, target, copyIfNull);
// Sale location
target.setSaleLocation(locationRepository.toVO(source.getSaleLocation()));
// Sale type
target.setSaleType(referentialDao.toVO(source.getSaleType()));
}
@Override
public void toEntity(ExpectedSaleVO source, ExpectedSale target, boolean copyIfNull) {
super.toEntity(source, target, copyIfNull);
// TODO : entity should be owned by a trip or a landing, not both -> validation to do in service
// Trip
Integer tripId = source.getTripId() != null ? source.getTripId() : (source.getTrip() != null ? source.getTrip().getId() : null);
if (copyIfNull || (tripId != null)) {
if (tripId == null) {
target.setTrip(null);
}
else {
target.setTrip(getReference(Trip.class, tripId));
}
}
// Landing
Integer landingId = source.getLandingId() != null ? source.getLandingId() : (source.getLanding() != null ? source.getLanding().getId() : null);
if (copyIfNull || (landingId != null)) {
if (landingId == null) {
target.setLanding(null);
}
else {
target.setLanding(getReference(Landing.class, landingId));
}
}
// Sale location
if (copyIfNull || source.getSaleLocation() != null) {
if (source.getSaleLocation() == null || source.getSaleLocation().getId() == null) {
target.setSaleLocation(null);
}
else {
target.setSaleLocation(getReference(Location.class, source.getSaleLocation().getId()));
}
}
// Sale type
if (copyIfNull || source.getSaleType() != null) {
if (source.getSaleType() == null || source.getSaleType().getId() == null) {
target.setSaleType(null);
}
else {
target.setSaleType(getReference(SaleType.class, source.getSaleType().getId()));
}
}
}
@Override
public List<ExpectedSaleVO> getAllByTripId(int tripId) {
return self.getExpectedSaleByTripId(tripId).stream().map(this::toVO).collect(Collectors.toList());
}
@Override
public List<ExpectedSaleVO> saveAllByTripId(int tripId, List<ExpectedSaleVO> sales) {
// Filter on non null objects
sales = sales.stream().filter(Objects::nonNull).collect(Collectors.toList());
// Get existing fishing areas
Set<Integer> existingIds = self.getAllIdsByTripId(tripId);
// Save
sales.forEach(sale -> {
// Set parent link
sale.setTripId(tripId);
save(sale);
existingIds.remove(sale.getId());
});
// Delete remaining objects
existingIds.forEach(this::deleteById);
return sales;
}
}
package net.sumaris.core.dao.data.sale;
/*-
* #%L
* SUMARiS:: Core
* %%
* Copyright (C) 2018 - 2020 SUMARiS Consortium
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this program. If not, see
* <http://www.gnu.org/licenses/gpl-3.0.html>.
* #L%
*/
import net.sumaris.core.dao.technical.jpa.BindableSpecification;
import net.sumaris.core.dao.technical.model.IEntity;
import net.sumaris.core.model.data.ExpectedSale;
import net.sumaris.core.vo.data.ExpectedSaleVO;
import org.springframework.data.jpa.domain.Specification;
import javax.persistence.criteria.ParameterExpression;
import java.util.List;
/**
* @author peck7 on 01/09/2020.
*/
public interface ExpectedSaleSpecifications {
String TRIP_ID_PARAM = "tripId";
default Specification<ExpectedSale> hasTripId(Integer tripId) {
BindableSpecification<ExpectedSale> specification = BindableSpecification.where((root, query, criteriaBuilder) -> {
ParameterExpression<Integer> param = criteriaBuilder.parameter(Integer.class, TRIP_ID_PARAM);
return criteriaBuilder.or(
criteriaBuilder.isNull(param),
criteriaBuilder.equal(root.get(ExpectedSale.Fields.TRIP).get(IEntity.Fields.ID), param)
);
});
specification.addBind(TRIP_ID_PARAM, tripId);
return specification;
}
List<ExpectedSaleVO> getAllByTripId(int tripId);
List<ExpectedSaleVO> saveAllByTripId(int tripId, List<ExpectedSaleVO> sales);
}
......@@ -69,6 +69,9 @@ public class Batch implements IDataEntity<Integer>,
@Column(name = "individual_count")
private Integer individualCount;
@Column(name = "subgroup_count")
private Integer subgroupCount;
@Column(length = IDataEntity.LENGTH_COMMENTS)
private String comments;
......
......@@ -85,6 +85,8 @@ public class DenormalizedBatch implements IEntity<Integer> {
@Column(name = "individual_count")
private Integer individualCount;
// TODO add subgroup_count ?
@Column(name = "indirect_individual_count")
private Integer indirectIndividualCount;
......
package net.sumaris.core.model.data;
/*-
* #%L
* SUMARiS:: Core
* %%
* Copyright (C) 2018 SUMARiS Consortium
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this program. If not, see
* <http://www.gnu.org/licenses/gpl-3.0.html>.
* #L%
*/
import lombok.Data;
import lombok.ToString;
import lombok.experimental.FieldNameConstants;
import net.sumaris.core.dao.technical.model.IEntity;
import net.sumaris.core.model.referential.SaleType;
import net.sumaris.core.model.referential.location.Location;
import org.hibernate.annotations.Cascade;
import javax.persistence.*;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
@Data
@FieldNameConstants
@Entity
@Table(name = "expected_sale")
public class ExpectedSale implements IEntity<Integer>,
IWithProductsEntity<Integer, Product> {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "EXPECTED_SALE_SEQ")
@SequenceGenerator(name = "EXPECTED_SALE_SEQ", sequenceName = "EXPECTED_SALE_SEQ", allocationSize = IDataEntity.SEQUENCE_ALLOCATION_SIZE)
private Integer id;
@Column(name = "sale_date")
private Date saleDate;
@ManyToOne(fetch = FetchType.EAGER, targetEntity = Location.class)
@JoinColumn(name = "sale_location_fk", nullable = false)
private Location saleLocation;
@ManyToOne(fetch = FetchType.EAGER, targetEntity = SaleType.class)
@JoinColumn(name = "sale_type_fk", nullable = false)
private SaleType saleType;
@OneToMany(fetch = FetchType.LAZY, targetEntity = Product.class, mappedBy = Product.Fields.EXPECTED_SALE)
@Cascade(org.hibernate.annotations.CascadeType.DELETE)
private List<Product> products = new ArrayList<>();
/* -- measurements -- */
@OneToMany(fetch = FetchType.LAZY, targetEntity = SaleMeasurement.class, mappedBy = SaleMeasurement.Fields.EXPECTED_SALE)
@Cascade(org.hibernate.annotations.CascadeType.DELETE)
private List<SaleMeasurement> measurements = new ArrayList<>();
/* -- parent -- */
@ManyToOne(fetch = FetchType.LAZY, targetEntity = Trip.class)
@JoinColumn(name = "trip_fk")
@ToString.Exclude
private Trip trip;
@ManyToOne(fetch = FetchType.LAZY, targetEntity = Landing.class)
@JoinColumn(name = "landing_fk")
@ToString.Exclude
private Landing landing;
}
......@@ -128,6 +128,10 @@ public class Landing implements IRootDataEntity<Integer>,
@Cascade(org.hibernate.annotations.CascadeType.DELETE)
private List<Product> products = new ArrayList<>();
@OneToMany(fetch = FetchType.LAZY, targetEntity = ExpectedSale.class, mappedBy = ExpectedSale.Fields.LANDING)
@Cascade(org.hibernate.annotations.CascadeType.DELETE)
private List<ExpectedSale> expectedSales = new ArrayList<>();
/* -- measurements -- */
@OneToMany(fetch = FetchType.LAZY, targetEntity = LandingMeasurement.class, mappedBy = LandingMeasurement.Fields.LANDING)
......
......@@ -154,6 +154,11 @@ public class Product
@ToString.Exclude
private Sale sale;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "expected_sale_fk")
@ToString.Exclude
private ExpectedSale expectedSale;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "batch_fk")
@ToString.Exclude
......
......@@ -94,7 +94,12 @@ public class SaleMeasurement implements IMeasurementEntity {
private Pmfm pmfm;
@ManyToOne(fetch = FetchType.LAZY, targetEntity = Sale.class)
@JoinColumn(name = "sale_fk", nullable = false)
@JoinColumn(name = "sale_fk")
@ToString.Exclude
private Sale sale;
@ManyToOne(fetch = FetchType.LAZY, targetEntity = ExpectedSale.class)
@JoinColumn(name = "expected_sale_fk")
@ToString.Exclude
private ExpectedSale expectedSale;
}
......@@ -154,6 +154,10 @@ public class Trip implements IRootDataEntity<Integer>,
@Cascade(org.hibernate.annotations.CascadeType.DELETE)
private List<Sale> sales = new ArrayList<>();
@OneToMany(fetch = FetchType.LAZY, targetEntity = ExpectedSale.class, mappedBy = ExpectedSale.Fields.TRIP)
@Cascade(org.hibernate.annotations.CascadeType.DELETE)
private List<ExpectedSale> expectedSales = new ArrayList<>();
@OneToMany(fetch = FetchType.LAZY, targetEntity = Landing.class, mappedBy = Landing.Fields.TRIP)
@Cascade(org.hibernate.annotations.CascadeType.DELETE)
private List<Landing> landings;
......