package pt.ist.internalBilling.domain; import java.util.Collections; import java.util.Set; import java.util.stream.Collectors; import java.util.stream.Stream; import org.fenixedu.bennu.core.domain.User; import org.fenixedu.bennu.core.security.Authenticate; import org.joda.time.DateTime; import com.google.gson.JsonObject; import com.google.gson.JsonParser; import pt.ist.expenditureTrackingSystem.domain.authorizations.Authorization; import pt.ist.expenditureTrackingSystem.domain.organization.CostCenter; import pt.ist.expenditureTrackingSystem.domain.organization.Unit; import pt.ist.fenixframework.Atomic; import pt.ist.internalBilling.BillingInformationHook; public class Billable extends Billable_Base { Billable(BillableService billableService, Unit financer, Beneficiary beneficiary) { setBillableService(billableService); if (!(financer instanceof CostCenter)) { throw new Error("only.cost.centers.are.allowed.to.be.financers"); } setUnit(financer); setBeneficiary(beneficiary); setBillableStatus(BillableStatus.PENDING_AUTHORIZATION); setServiceStatus(ServiceStatus.PENDING_ACTIVATION); } void log(final String description) { new BillableLog(this, description); } @Atomic public void authorize() { if (getBillableStatus() == BillableStatus.PENDING_AUTHORIZATION) { setBillableStatus(BillableStatus.AUTHORIZED); log("Authorized subscription of service " + getBillableService().getTitle() + " for unit " + getUnit().getPresentationName() + " to user " + getBeneficiary().getPresentationName() + " with configuration " + getConfiguration()); BillingInformationHook.HOOKS.forEach(h -> h.authorize(this)); } } @Atomic public void revoke() { if (getBillableStatus() != BillableStatus.REVOKED) { setBillableStatus(BillableStatus.REVOKED); log("Revoked subscription of service " + getBillableService().getTitle() + " for unit " + getUnit().getPresentationName() + " to user " + getBeneficiary().getPresentationName() + " with configuration " + getConfiguration()); BillingInformationHook.HOOKS.forEach(h -> h.revoke(this)); } } public static Set<Billable> pendingAuthorization() { final User user = Authenticate.getUser(); return user == null ? Collections.emptySet() : user.getExpenditurePerson().getAuthorizationsSet().stream() .filter(a -> a.isValid()).flatMap(a -> units(a)).flatMap(u -> u.getBillableSet().stream()) .filter(b -> b.getBillableStatus() == BillableStatus.PENDING_AUTHORIZATION).collect(Collectors.toSet()); } private static Stream<Unit> units(final Authorization a) { final Unit unit = a.getUnit(); return Stream.concat(Stream.of(unit), childUnitsWithNoAuthority(unit)); } private static Stream<Unit> childUnitsWithNoAuthority(final Unit unit) { Stream<Unit> result = Stream.empty(); for (final Unit child : unit.getSubUnitsSet()) { if (child.getAuthorizationsSet().isEmpty()) { result = Stream.concat(result, Stream.of(child)); result = Stream.concat(result, childUnitsWithNoAuthority(child)); } } return result; } public JsonObject getConfigurationAsJson() { final String config = getConfiguration(); return config == null ? new JsonObject() : new JsonParser().parse(config).getAsJsonObject(); } public boolean isCurrentUserAllowedToView() { final Unit unit = getUnit(); return InternalBillingService.canViewUnitServices(unit) || isCurrentUserBenificiary(); } public boolean isCurrentUserBenificiary() { final Beneficiary beneficiary = getBeneficiary(); return beneficiary instanceof UserBeneficiary && ((UserBeneficiary) beneficiary).getUser() == Authenticate.getUser(); } @Atomic public void setUserFromCurrentBillable(final User user) { new CurrentBillableHistory(this, user); log("Set current billing unit to " + getUnit().getPresentationName() + " for user " + getBeneficiary().getPresentationName()); } public static Billable forUserOnDate(final User user, final DateTime dt) { final CurrentBillableHistory current = user.getCurrentBillableHistory(); return forUserOnDate(user, dt, current); } public static Billable forUserOnDate(final User user, final DateTime dt, final CurrentBillableHistory current) { if (current != null) { if (current.getWhenInstant().isBefore(dt)) { final Billable billable = current.getBillable(); if (billable.getBillableStatus() == BillableStatus.AUTHORIZED) { return current.getBillable(); } } return forUserOnDate(user, dt, current.getPreviouseHistory()); } return null; } }