Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 893b665dc2 | |||
| 2a48f440af | |||
| e55d7ad07f | |||
| 48bd9983fc |
@@ -36,7 +36,7 @@ import java.util.Map;
|
|||||||
|
|
||||||
public class Constants {
|
public class Constants {
|
||||||
|
|
||||||
public final static long DB_VERSION = 6;
|
public final static long DB_VERSION = 7;
|
||||||
|
|
||||||
public final static String DEF_ADMIN = "admin";
|
public final static String DEF_ADMIN = "admin";
|
||||||
public final static String DEF_ADMIN_PASSWD = "admin";
|
public final static String DEF_ADMIN_PASSWD = "admin";
|
||||||
|
|||||||
@@ -63,6 +63,8 @@ public class RequirementBase extends BaseData implements FilterableRequirement,
|
|||||||
@JoinColumn(name = "SEASON_ID")
|
@JoinColumn(name = "SEASON_ID")
|
||||||
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
|
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
|
||||||
private Season season;
|
private Season season;
|
||||||
|
@Column(name = "APPROVE_DATE")
|
||||||
|
private Date approveDate;
|
||||||
|
|
||||||
public RequirementBase() {
|
public RequirementBase() {
|
||||||
authorization = new ArrayList<AuthItem>();
|
authorization = new ArrayList<AuthItem>();
|
||||||
@@ -166,4 +168,12 @@ public class RequirementBase extends BaseData implements FilterableRequirement,
|
|||||||
public void setSeason(Season season) {
|
public void setSeason(Season season) {
|
||||||
this.season = season;
|
this.season = season;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Date getApproveDate() {
|
||||||
|
return approveDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setApproveDate(Date approveDate) {
|
||||||
|
this.approveDate = approveDate;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ import java.util.List;
|
|||||||
@Entity
|
@Entity
|
||||||
@Table(name = "TRIP_BILL")
|
@Table(name = "TRIP_BILL")
|
||||||
@Indexed
|
@Indexed
|
||||||
|
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
|
||||||
public class TripBill extends BaseData implements EntityWithAttachment, SeasonsAware {
|
public class TripBill extends BaseData implements EntityWithAttachment, SeasonsAware {
|
||||||
|
|
||||||
@OneToOne(fetch = FetchType.EAGER)
|
@OneToOne(fetch = FetchType.EAGER)
|
||||||
|
|||||||
@@ -22,8 +22,6 @@ public class TripBillApproval extends RequirementBase {
|
|||||||
@Transient
|
@Transient
|
||||||
private boolean billForPassenger;
|
private boolean billForPassenger;
|
||||||
@Transient
|
@Transient
|
||||||
private Date approveDate;
|
|
||||||
@Transient
|
|
||||||
private Date tripDate;
|
private Date tripDate;
|
||||||
|
|
||||||
public boolean isBillForPassenger() {
|
public boolean isBillForPassenger() {
|
||||||
@@ -42,14 +40,6 @@ public class TripBillApproval extends RequirementBase {
|
|||||||
this.tripDate = tripDate;
|
this.tripDate = tripDate;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Date getApproveDate() {
|
|
||||||
return approveDate;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setApproveDate(Date approveDate) {
|
|
||||||
this.approveDate = approveDate;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getNumser() {
|
public String getNumser() {
|
||||||
|
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ public class TripBillApprovalFilter implements Filter<TripBillApproval>
|
|||||||
boolean foundPaid = BooleanUtils.isEqualByBooleanValue(item.getBill().getPaid(), condition.getBill().getPaid());
|
boolean foundPaid = BooleanUtils.isEqualByBooleanValue(item.getBill().getPaid(), condition.getBill().getPaid());
|
||||||
boolean foundPaidDate = DateTimeUtils.isEqualByDateForFilter(item.getBill().getPaidDate(), condition.getBill().getPaidDate());
|
boolean foundPaidDate = DateTimeUtils.isEqualByDateForFilter(item.getBill().getPaidDate(), condition.getBill().getPaidDate());
|
||||||
boolean foundPassenger = (item.getBill().getOwnedBy() != item.getBill().getRequirement().getOwnedBy()) == condition.isBillForPassenger();
|
boolean foundPassenger = (item.getBill().getOwnedBy() != item.getBill().getRequirement().getOwnedBy()) == condition.isBillForPassenger();
|
||||||
boolean foundApproveDate = DateTimeUtils.isEqualByDateForFilter(item.getLastApproveDate(), condition.getApproveDate());
|
boolean foundApproveDate = DateTimeUtils.isEqualByDateForFilter(item.getApproveDate(), condition.getApproveDate());
|
||||||
boolean foundTripDate = DateTimeUtils.isEqualByDateForFilter(item.getBill().getRequirement().getTripDate(), condition.getTripDate());
|
boolean foundTripDate = DateTimeUtils.isEqualByDateForFilter(item.getBill().getRequirement().getTripDate(), condition.getTripDate());
|
||||||
return foundNumser && foundReqDate && foundDescription && foundFrom && foundTo && foundWorkgroup && foundCentre && foundOwner && foundPaid
|
return foundNumser && foundReqDate && foundDescription && foundFrom && foundTo && foundWorkgroup && foundCentre && foundOwner && foundPaid
|
||||||
&& foundPaidDate && foundPassenger && foundApproveDate && foundTripDate;
|
&& foundPaidDate && foundPassenger && foundApproveDate && foundTripDate;
|
||||||
|
|||||||
@@ -0,0 +1,306 @@
|
|||||||
|
package info.bukova.isspst.security;
|
||||||
|
|
||||||
|
import org.springframework.ldap.core.DirContextOperations;
|
||||||
|
import org.springframework.ldap.core.DistinguishedName;
|
||||||
|
import org.springframework.ldap.support.LdapUtils;
|
||||||
|
import org.springframework.security.authentication.AccountExpiredException;
|
||||||
|
import org.springframework.security.authentication.BadCredentialsException;
|
||||||
|
import org.springframework.security.authentication.CredentialsExpiredException;
|
||||||
|
import org.springframework.security.authentication.DisabledException;
|
||||||
|
import org.springframework.security.authentication.LockedException;
|
||||||
|
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||||
|
import org.springframework.security.core.GrantedAuthority;
|
||||||
|
import org.springframework.security.core.authority.AuthorityUtils;
|
||||||
|
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||||
|
import org.springframework.security.ldap.SpringSecurityLdapTemplate;
|
||||||
|
import org.springframework.security.ldap.authentication.AbstractLdapAuthenticationProvider;
|
||||||
|
import org.springframework.util.Assert;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
|
import javax.naming.AuthenticationException;
|
||||||
|
import javax.naming.Context;
|
||||||
|
import javax.naming.NamingException;
|
||||||
|
import javax.naming.OperationNotSupportedException;
|
||||||
|
import javax.naming.directory.DirContext;
|
||||||
|
import javax.naming.directory.SearchControls;
|
||||||
|
import javax.naming.ldap.InitialLdapContext;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Hashtable;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
public class AdAuthenticationProvider extends AbstractLdapAuthenticationProvider{
|
||||||
|
private static final Pattern SUB_ERROR_CODE = Pattern.compile(".*data\\s([0-9a-f]{3,4}).*");
|
||||||
|
|
||||||
|
// Error codes
|
||||||
|
private static final int USERNAME_NOT_FOUND = 0x525;
|
||||||
|
private static final int INVALID_PASSWORD = 0x52e;
|
||||||
|
private static final int NOT_PERMITTED = 0x530;
|
||||||
|
private static final int PASSWORD_EXPIRED = 0x532;
|
||||||
|
private static final int ACCOUNT_DISABLED = 0x533;
|
||||||
|
private static final int ACCOUNT_EXPIRED = 0x701;
|
||||||
|
private static final int PASSWORD_NEEDS_RESET = 0x773;
|
||||||
|
private static final int ACCOUNT_LOCKED = 0x775;
|
||||||
|
|
||||||
|
private final String domain;
|
||||||
|
private final String rootDn;
|
||||||
|
private final String url;
|
||||||
|
private final String upnSuffix;
|
||||||
|
private boolean convertSubErrorCodesToExceptions;
|
||||||
|
|
||||||
|
// Only used to allow tests to substitute a mock LdapContext
|
||||||
|
ContextFactory contextFactory = new ContextFactory();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param domain the domain for which authentication should take place
|
||||||
|
*/
|
||||||
|
// public ActiveDirectoryLdapAuthenticationProvider(String domain) {
|
||||||
|
// this (domain, null);
|
||||||
|
// }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param domain the domain name (may be null or empty)
|
||||||
|
* @param url an LDAP url (or multiple URLs)
|
||||||
|
*/
|
||||||
|
public AdAuthenticationProvider(String domain, String upnSuffix, String url) {
|
||||||
|
Assert.isTrue(StringUtils.hasText(url), "Url cannot be empty");
|
||||||
|
this.domain = StringUtils.hasText(domain) ? domain.toLowerCase() : null;
|
||||||
|
//this.url = StringUtils.hasText(url) ? url : null;
|
||||||
|
this.url = url;
|
||||||
|
this.upnSuffix = upnSuffix;
|
||||||
|
rootDn = this.domain == null ? null : rootDnFromDomain(this.domain);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected DirContextOperations doAuthentication(UsernamePasswordAuthenticationToken auth) {
|
||||||
|
String username = auth.getName();
|
||||||
|
String password = (String)auth.getCredentials();
|
||||||
|
|
||||||
|
DirContext ctx = bindAsUser(username, password);
|
||||||
|
|
||||||
|
try {
|
||||||
|
return searchForUser(ctx, username);
|
||||||
|
|
||||||
|
} catch (NamingException e) {
|
||||||
|
logger.error("Failed to locate directory entry for authenticated user: " + username, e);
|
||||||
|
throw badCredentials();
|
||||||
|
} finally {
|
||||||
|
LdapUtils.closeContext(ctx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates the user authority list from the values of the {@code memberOf} attribute obtained from the user's
|
||||||
|
* Active Directory entry.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected Collection<? extends GrantedAuthority> loadUserAuthorities(DirContextOperations userData, String username, String password) {
|
||||||
|
String[] groups = userData.getStringAttributes("memberOf");
|
||||||
|
|
||||||
|
if (groups == null) {
|
||||||
|
logger.debug("No values for 'memberOf' attribute.");
|
||||||
|
|
||||||
|
return AuthorityUtils.NO_AUTHORITIES;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (logger.isDebugEnabled()) {
|
||||||
|
logger.debug("'memberOf' attribute values: " + Arrays.asList(groups));
|
||||||
|
}
|
||||||
|
|
||||||
|
ArrayList<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>(groups.length);
|
||||||
|
|
||||||
|
for (String group : groups) {
|
||||||
|
authorities.add(new SimpleGrantedAuthority(new DistinguishedName(group).removeLast().getValue()));
|
||||||
|
}
|
||||||
|
|
||||||
|
return authorities;
|
||||||
|
}
|
||||||
|
|
||||||
|
private DirContext bindAsUser(String username, String password) {
|
||||||
|
// TODO. add DNS lookup based on domain
|
||||||
|
final String bindUrl = url;
|
||||||
|
|
||||||
|
Hashtable<String,String> env = new Hashtable<String,String>();
|
||||||
|
env.put(Context.SECURITY_AUTHENTICATION, "simple");
|
||||||
|
String bindPrincipal = createBindPrincipal(username);
|
||||||
|
env.put(Context.SECURITY_PRINCIPAL, bindPrincipal);
|
||||||
|
env.put(Context.PROVIDER_URL, bindUrl);
|
||||||
|
env.put(Context.SECURITY_CREDENTIALS, password);
|
||||||
|
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
|
||||||
|
|
||||||
|
try {
|
||||||
|
return contextFactory.createContext(env);
|
||||||
|
} catch (NamingException e) {
|
||||||
|
if ((e instanceof AuthenticationException) || (e instanceof OperationNotSupportedException)) {
|
||||||
|
handleBindException(bindPrincipal, e);
|
||||||
|
throw badCredentials();
|
||||||
|
} else {
|
||||||
|
throw LdapUtils.convertLdapException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void handleBindException(String bindPrincipal, NamingException exception) {
|
||||||
|
if (logger.isDebugEnabled()) {
|
||||||
|
logger.debug("Authentication for " + bindPrincipal + " failed:" + exception);
|
||||||
|
}
|
||||||
|
|
||||||
|
int subErrorCode = parseSubErrorCode(exception.getMessage());
|
||||||
|
|
||||||
|
if (subErrorCode > 0) {
|
||||||
|
logger.info("Active Directory authentication failed: " + subCodeToLogMessage(subErrorCode));
|
||||||
|
|
||||||
|
if (convertSubErrorCodesToExceptions) {
|
||||||
|
raiseExceptionForErrorCode(subErrorCode);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
logger.debug("Failed to locate AD-specific sub-error code in message");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int parseSubErrorCode(String message) {
|
||||||
|
Matcher m = SUB_ERROR_CODE.matcher(message);
|
||||||
|
|
||||||
|
if (m.matches()) {
|
||||||
|
return Integer.parseInt(m.group(1), 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void raiseExceptionForErrorCode(int code) {
|
||||||
|
switch (code) {
|
||||||
|
case PASSWORD_EXPIRED:
|
||||||
|
throw new CredentialsExpiredException(messages.getMessage("LdapAuthenticationProvider.credentialsExpired",
|
||||||
|
"User credentials have expired"));
|
||||||
|
case ACCOUNT_DISABLED:
|
||||||
|
throw new DisabledException(messages.getMessage("LdapAuthenticationProvider.disabled",
|
||||||
|
"User is disabled"));
|
||||||
|
case ACCOUNT_EXPIRED:
|
||||||
|
throw new AccountExpiredException(messages.getMessage("LdapAuthenticationProvider.expired",
|
||||||
|
"User account has expired"));
|
||||||
|
case ACCOUNT_LOCKED:
|
||||||
|
throw new LockedException(messages.getMessage("LdapAuthenticationProvider.locked",
|
||||||
|
"User account is locked"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String subCodeToLogMessage(int code) {
|
||||||
|
switch (code) {
|
||||||
|
case USERNAME_NOT_FOUND:
|
||||||
|
return "User was not found in directory";
|
||||||
|
case INVALID_PASSWORD:
|
||||||
|
return "Supplied password was invalid";
|
||||||
|
case NOT_PERMITTED:
|
||||||
|
return "User not permitted to logon at this time";
|
||||||
|
case PASSWORD_EXPIRED:
|
||||||
|
return "Password has expired";
|
||||||
|
case ACCOUNT_DISABLED:
|
||||||
|
return "Account is disabled";
|
||||||
|
case ACCOUNT_EXPIRED:
|
||||||
|
return "Account expired";
|
||||||
|
case PASSWORD_NEEDS_RESET:
|
||||||
|
return "User must reset password";
|
||||||
|
case ACCOUNT_LOCKED:
|
||||||
|
return "Account locked";
|
||||||
|
}
|
||||||
|
|
||||||
|
return "Unknown (error code " + Integer.toHexString(code) +")";
|
||||||
|
}
|
||||||
|
|
||||||
|
private BadCredentialsException badCredentials() {
|
||||||
|
return new BadCredentialsException(messages.getMessage(
|
||||||
|
"LdapAuthenticationProvider.badCredentials", "Bad credentials"));
|
||||||
|
}
|
||||||
|
|
||||||
|
private DirContextOperations searchForUser(DirContext ctx, String username) throws NamingException {
|
||||||
|
SearchControls searchCtls = new SearchControls();
|
||||||
|
searchCtls.setSearchScope(SearchControls.SUBTREE_SCOPE);
|
||||||
|
|
||||||
|
String searchFilter = "(&(objectClass=user)(userPrincipalName={0}))";
|
||||||
|
|
||||||
|
final String bindPrincipal = createBindPrincipal(username);
|
||||||
|
final String searchDn = createSearchDn(username);
|
||||||
|
|
||||||
|
String searchRoot = rootDn != null ? rootDn : searchRootFromPrincipal(bindPrincipal);
|
||||||
|
|
||||||
|
DirContextOperations ctxOp;
|
||||||
|
|
||||||
|
try {
|
||||||
|
ctxOp = SpringSecurityLdapTemplate.searchForSingleEntryInternal(ctx, searchCtls, searchRoot, searchFilter,
|
||||||
|
new Object[]{searchDn});
|
||||||
|
|
||||||
|
if (ctxOp != null) {
|
||||||
|
return ctxOp;
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.warn("UPN " + searchDn + " not found. Falling back to search with domain UPN suffix.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return SpringSecurityLdapTemplate.searchForSingleEntryInternal(ctx, searchCtls, searchRoot, searchFilter,
|
||||||
|
new Object[]{bindPrincipal});
|
||||||
|
}
|
||||||
|
|
||||||
|
private String searchRootFromPrincipal(String bindPrincipal) {
|
||||||
|
int atChar = bindPrincipal.lastIndexOf('@');
|
||||||
|
|
||||||
|
if (atChar < 0) {
|
||||||
|
logger.debug("User principal '" + bindPrincipal + "' does not contain the domain, and no domain has been configured");
|
||||||
|
throw badCredentials();
|
||||||
|
}
|
||||||
|
|
||||||
|
return rootDnFromDomain(bindPrincipal.substring(atChar+ 1, bindPrincipal.length()));
|
||||||
|
}
|
||||||
|
|
||||||
|
private String rootDnFromDomain(String domain) {
|
||||||
|
String[] tokens = StringUtils.tokenizeToStringArray(domain, ".");
|
||||||
|
StringBuilder root = new StringBuilder();
|
||||||
|
|
||||||
|
for (String token : tokens) {
|
||||||
|
if (root.length() > 0) {
|
||||||
|
root.append(',');
|
||||||
|
}
|
||||||
|
root.append("dc=").append(token);
|
||||||
|
}
|
||||||
|
|
||||||
|
return root.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
String createBindPrincipal(String username) {
|
||||||
|
if (domain == null || username.toLowerCase().endsWith(domain)) {
|
||||||
|
return username;
|
||||||
|
}
|
||||||
|
|
||||||
|
return username + "@" + domain;
|
||||||
|
}
|
||||||
|
|
||||||
|
String createSearchDn(String username) {
|
||||||
|
if (upnSuffix == null) {
|
||||||
|
return createBindPrincipal(username);
|
||||||
|
}
|
||||||
|
|
||||||
|
return username + "@" + upnSuffix;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* By default, a failed authentication (LDAP error 49) will result in a {@code BadCredentialsException}.
|
||||||
|
* <p>
|
||||||
|
* If this property is set to {@code true}, the exception message from a failed bind attempt will be parsed
|
||||||
|
* for the AD-specific error code and a {@link CredentialsExpiredException}, {@link DisabledException},
|
||||||
|
* {@link AccountExpiredException} or {@link LockedException} will be thrown for the corresponding codes. All
|
||||||
|
* other codes will result in the default {@code BadCredentialsException}.
|
||||||
|
*
|
||||||
|
* @param convertSubErrorCodesToExceptions {@code true} to raise an exception based on the AD error code.
|
||||||
|
*/
|
||||||
|
public void setConvertSubErrorCodesToExceptions(boolean convertSubErrorCodesToExceptions) {
|
||||||
|
this.convertSubErrorCodesToExceptions = convertSubErrorCodesToExceptions;
|
||||||
|
}
|
||||||
|
|
||||||
|
static class ContextFactory {
|
||||||
|
DirContext createContext(Hashtable<?,?> env) throws NamingException {
|
||||||
|
return new InitialLdapContext(env, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,9 +1,20 @@
|
|||||||
package info.bukova.isspst.services.dbinfo;
|
package info.bukova.isspst.services.dbinfo;
|
||||||
|
|
||||||
import info.bukova.isspst.Constants;
|
import info.bukova.isspst.Constants;
|
||||||
|
import info.bukova.isspst.dao.BaseDao;
|
||||||
|
import info.bukova.isspst.dao.RequirementDao;
|
||||||
|
import info.bukova.isspst.dao.TripBillApprovalDao;
|
||||||
|
import info.bukova.isspst.dao.TripRequirementDao;
|
||||||
import info.bukova.isspst.data.DbInfo;
|
import info.bukova.isspst.data.DbInfo;
|
||||||
|
import info.bukova.isspst.data.RequirementBase;
|
||||||
|
import info.bukova.isspst.data.RequirementState;
|
||||||
import info.bukova.isspst.services.AbstractService;
|
import info.bukova.isspst.services.AbstractService;
|
||||||
|
import info.bukova.isspst.services.requirement.RequirementBaseService;
|
||||||
|
import info.bukova.isspst.services.requirement.RequirementService;
|
||||||
|
import info.bukova.isspst.services.requirement.TripRequirementService;
|
||||||
|
import info.bukova.isspst.services.tripbill.TripBillApprovalService;
|
||||||
import org.hibernate.SQLQuery;
|
import org.hibernate.SQLQuery;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@@ -11,6 +22,20 @@ import java.util.List;
|
|||||||
|
|
||||||
public class DbInfoServiceImpl extends AbstractService<DbInfo> implements DbInfoService
|
public class DbInfoServiceImpl extends AbstractService<DbInfo> implements DbInfoService
|
||||||
{
|
{
|
||||||
|
@Autowired
|
||||||
|
private TripBillApprovalService tripBillApprovalService;
|
||||||
|
@Autowired
|
||||||
|
private TripBillApprovalDao tripBillApprovalDao;
|
||||||
|
@Autowired
|
||||||
|
private TripRequirementService tripRequirement;
|
||||||
|
@Autowired
|
||||||
|
private TripRequirementDao tripRequirementDao;
|
||||||
|
@Autowired
|
||||||
|
private RequirementService requirementService;
|
||||||
|
@Autowired
|
||||||
|
private RequirementDao requirementDao;
|
||||||
|
|
||||||
|
|
||||||
private DbInfo getDbInfo()
|
private DbInfo getDbInfo()
|
||||||
{
|
{
|
||||||
DbInfo dbInfo = null;
|
DbInfo dbInfo = null;
|
||||||
@@ -211,10 +236,26 @@ public class DbInfoServiceImpl extends AbstractService<DbInfo> implements DbInfo
|
|||||||
sq.executeUpdate();
|
sq.executeUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (dbVersion < 7) {
|
||||||
|
setApproveDate((RequirementBaseService)tripBillApprovalService, (BaseDao)tripBillApprovalDao);
|
||||||
|
setApproveDate((RequirementBaseService)tripRequirement, (BaseDao)tripRequirementDao);
|
||||||
|
setApproveDate((RequirementBaseService)requirementService, (BaseDao)requirementDao);
|
||||||
|
}
|
||||||
|
|
||||||
this.updateDatabaseVersion();
|
this.updateDatabaseVersion();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void setApproveDate(RequirementBaseService<RequirementBase> service, BaseDao<RequirementBase> daoReq) {
|
||||||
|
for (RequirementBase req : service.getAll()) {
|
||||||
|
if (req.getState() == RequirementState.APPROVED) {
|
||||||
|
service.loadAuthItems(req);
|
||||||
|
req.setApproveDate(req.getLastApproveDate());
|
||||||
|
daoReq.modify(req);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional
|
@Transactional
|
||||||
public void updateDatabaseVersion()
|
public void updateDatabaseVersion()
|
||||||
|
|||||||
@@ -289,6 +289,7 @@ public abstract class RequirementBaseServiceImpl<T extends RequirementBase> exte
|
|||||||
|
|
||||||
if (getNextWorkflow(e) == null) {
|
if (getNextWorkflow(e) == null) {
|
||||||
e.setState(RequirementState.APPROVED);
|
e.setState(RequirementState.APPROVED);
|
||||||
|
e.setApproveDate(approveDate);
|
||||||
} else {
|
} else {
|
||||||
e.setState(RequirementState.PARTIALLY);
|
e.setState(RequirementState.PARTIALLY);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -69,11 +69,7 @@ public class ListViewModel<T extends DataModel> extends DocumentViewModel
|
|||||||
{
|
{
|
||||||
super.initDocumentViewModel();
|
super.initDocumentViewModel();
|
||||||
seasons = seasonService.getAllSeasons();
|
seasons = seasonService.getAllSeasons();
|
||||||
|
selSeason = seasonService.getActive();
|
||||||
Map<String, String[]> map = Executions.getCurrent().getParameterMap();
|
|
||||||
if (map.get("select") == null) {
|
|
||||||
selSeason = seasonService.getActive();
|
|
||||||
}
|
|
||||||
setHqlFilter();
|
setHqlFilter();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -328,9 +324,6 @@ public class ListViewModel<T extends DataModel> extends DocumentViewModel
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (id > 0) {
|
if (id > 0) {
|
||||||
selSeason = null;
|
|
||||||
setHqlFilter();
|
|
||||||
dataList = getListFromService();
|
|
||||||
for (int i = 0; i < dataList.size(); i++) {
|
for (int i = 0; i < dataList.size(); i++) {
|
||||||
if (dataList.get(i).getId() == id) {
|
if (dataList.get(i).getId() == id) {
|
||||||
selIndex = i;
|
selIndex = i;
|
||||||
|
|||||||
+39
-2
@@ -1,8 +1,11 @@
|
|||||||
package info.bukova.isspst.ui.main.orders.requirements;
|
package info.bukova.isspst.ui.main.orders.requirements;
|
||||||
|
|
||||||
|
import info.bukova.isspst.data.Limit;
|
||||||
import info.bukova.isspst.data.Requirement;
|
import info.bukova.isspst.data.Requirement;
|
||||||
import info.bukova.isspst.data.Workgroup;
|
import info.bukova.isspst.data.Workgroup;
|
||||||
import info.bukova.isspst.filters.RequirementFilter;
|
import info.bukova.isspst.filters.RequirementFilter;
|
||||||
|
import info.bukova.isspst.services.invoicing.InvoicingService;
|
||||||
|
import info.bukova.isspst.services.limits.LimitService;
|
||||||
import info.bukova.isspst.services.requirement.RequirementService;
|
import info.bukova.isspst.services.requirement.RequirementService;
|
||||||
import info.bukova.isspst.services.workgroups.WorkgroupService;
|
import info.bukova.isspst.services.workgroups.WorkgroupService;
|
||||||
import info.bukova.isspst.ui.requirement.RequirementSubpage;
|
import info.bukova.isspst.ui.requirement.RequirementSubpage;
|
||||||
@@ -25,6 +28,12 @@ public class ReqListMyWorkgroups extends RequirementSubpage<Requirement>
|
|||||||
@WireVariable
|
@WireVariable
|
||||||
protected WorkgroupService workgroupService;
|
protected WorkgroupService workgroupService;
|
||||||
|
|
||||||
|
@WireVariable
|
||||||
|
protected LimitService limitService;
|
||||||
|
|
||||||
|
@WireVariable
|
||||||
|
protected InvoicingService invoicingService;
|
||||||
|
|
||||||
public List<Workgroup> getCentres()
|
public List<Workgroup> getCentres()
|
||||||
{
|
{
|
||||||
return workgroupService.getCentres();
|
return workgroupService.getCentres();
|
||||||
@@ -73,10 +82,38 @@ public class ReqListMyWorkgroups extends RequirementSubpage<Requirement>
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@NotifyChange({ "dataBean", "ableToDelete", "canApprove", "invoicedAmount" })
|
@NotifyChange({ "dataBean", "ableToDelete", "canApprove", "invoicedAmount", "workgroupLimit", "workgroupInvoiced" })
|
||||||
public void setDataBean(Requirement data) {
|
public void setDataBean(Requirement data) {
|
||||||
super.setDataBean(data);
|
super.setDataBean(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public BigDecimal getWorkgroupLimit() {
|
||||||
|
if (getDataBean() != null && getDataBean().getWorkgroup() != null) {
|
||||||
|
Limit limit = limitService.getForWorkgroup(getDataBean().getWorkgroup());
|
||||||
|
|
||||||
|
if (limit == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return limit.getLimit();
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BigDecimal getWorkgroupInvoiced() {
|
||||||
|
if (getDataBean() != null && getDataBean().getWorkgroup() != null) {
|
||||||
|
BigDecimal invoiced = invoicingService.totalInvoicedForWorkgroup(getDataBean().getWorkgroup());
|
||||||
|
|
||||||
|
if (invoiced == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return invoiced;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,12 +20,7 @@ public class TripBillListAll extends TripBillListBase {
|
|||||||
@Override
|
@Override
|
||||||
protected List<TripBillApproval> getListFromService() {
|
protected List<TripBillApproval> getListFromService() {
|
||||||
try {
|
try {
|
||||||
List<TripBillApproval> list = getReqService().getAll();
|
return getReqService().getAll();
|
||||||
for (TripBillApproval item : list)
|
|
||||||
{
|
|
||||||
getReqService().loadAuthItems(item);
|
|
||||||
}
|
|
||||||
return list;
|
|
||||||
} catch (AccessDeniedException e) {
|
} catch (AccessDeniedException e) {
|
||||||
BindUtils.postGlobalCommand(null, null, "disableAll", null);
|
BindUtils.postGlobalCommand(null, null, "disableAll", null);
|
||||||
return new ArrayList<TripBillApproval>();
|
return new ArrayList<TripBillApproval>();
|
||||||
|
|||||||
@@ -20,12 +20,7 @@ public class TripBillListCentre extends TripBillListBase {
|
|||||||
@Override
|
@Override
|
||||||
protected List<TripBillApproval> getListFromService() {
|
protected List<TripBillApproval> getListFromService() {
|
||||||
try {
|
try {
|
||||||
List<TripBillApproval> list = getReqService().getCentreReq();
|
return getReqService().getCentreReq();
|
||||||
for (TripBillApproval item : list)
|
|
||||||
{
|
|
||||||
getReqService().loadAuthItems(item);
|
|
||||||
}
|
|
||||||
return list;
|
|
||||||
} catch (AccessDeniedException e) {
|
} catch (AccessDeniedException e) {
|
||||||
BindUtils.postGlobalCommand(null, null, "disableCentre", null);
|
BindUtils.postGlobalCommand(null, null, "disableCentre", null);
|
||||||
return new ArrayList<TripBillApproval>();
|
return new ArrayList<TripBillApproval>();
|
||||||
|
|||||||
@@ -20,12 +20,7 @@ public class TripBillListWorkgroup extends TripBillListBase {
|
|||||||
@Override
|
@Override
|
||||||
protected List<TripBillApproval> getListFromService() {
|
protected List<TripBillApproval> getListFromService() {
|
||||||
try {
|
try {
|
||||||
List<TripBillApproval> list = getReqService().getWorkgroupReq();
|
return getReqService().getWorkgroupReq();
|
||||||
for (TripBillApproval item : list)
|
|
||||||
{
|
|
||||||
getReqService().loadAuthItems(item);
|
|
||||||
}
|
|
||||||
return list;
|
|
||||||
} catch (AccessDeniedException e) {
|
} catch (AccessDeniedException e) {
|
||||||
BindUtils.postGlobalCommand(null, null, "disableWorkgroup", null);
|
BindUtils.postGlobalCommand(null, null, "disableWorkgroup", null);
|
||||||
return new ArrayList<TripBillApproval>();
|
return new ArrayList<TripBillApproval>();
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
ad.domain=bukova.net
|
ad.domain=bukova.net
|
||||||
|
ad.upnSuffix=bukova.info
|
||||||
ad.ldapUrl=ldap://192.168.25.110/
|
ad.ldapUrl=ldap://192.168.25.110/
|
||||||
ad.allowedGroup=ucitele
|
ad.allowedGroup=ucitele
|
||||||
Binary file not shown.
@@ -1,7 +1,9 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<!-- Created with Jaspersoft Studio version 6.6.0.final using JasperReports Library version 6.6.0 -->
|
|
||||||
<jasperReport xmlns="http://jasperreports.sourceforge.net/jasperreports" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports http://jasperreports.sourceforge.net/xsd/jasperreport.xsd" name="TripBills" pageWidth="595" pageHeight="842" columnWidth="555" leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20" uuid="b63eddc4-7326-45c4-99b4-fc35d6e98179">
|
<jasperReport xmlns="http://jasperreports.sourceforge.net/jasperreports" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports http://jasperreports.sourceforge.net/xsd/jasperreport.xsd" name="TripBills" pageWidth="595" pageHeight="842" columnWidth="555" leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20" uuid="b63eddc4-7326-45c4-99b4-fc35d6e98179">
|
||||||
<property name="com.jaspersoft.studio.data.defaultdataadapter" value="One Empty Record"/>
|
<property name="com.jaspersoft.studio.data.defaultdataadapter" value="One Empty Record"/>
|
||||||
|
<property name="ireport.zoom" value="1.9487171000000014"/>
|
||||||
|
<property name="ireport.x" value="0"/>
|
||||||
|
<property name="ireport.y" value="0"/>
|
||||||
<queryString>
|
<queryString>
|
||||||
<![CDATA[]]>
|
<![CDATA[]]>
|
||||||
</queryString>
|
</queryString>
|
||||||
@@ -19,7 +21,7 @@
|
|||||||
<title>
|
<title>
|
||||||
<band height="23" splitType="Stretch">
|
<band height="23" splitType="Stretch">
|
||||||
<staticText>
|
<staticText>
|
||||||
<reportElement x="203" y="0" width="212" height="20" uuid="bc6cd7eb-bb1a-4114-b37d-ac64e951ca84"/>
|
<reportElement x="0" y="0" width="550" height="20" uuid="bc6cd7eb-bb1a-4114-b37d-ac64e951ca84"/>
|
||||||
<textElement textAlignment="Center">
|
<textElement textAlignment="Center">
|
||||||
<font size="14" isBold="true" pdfFontName="Helvetica-Bold" pdfEncoding="Cp1250" isPdfEmbedded="true"/>
|
<font size="14" isBold="true" pdfFontName="Helvetica-Bold" pdfEncoding="Cp1250" isPdfEmbedded="true"/>
|
||||||
</textElement>
|
</textElement>
|
||||||
@@ -75,7 +77,7 @@
|
|||||||
<text><![CDATA[Cíl]]></text>
|
<text><![CDATA[Cíl]]></text>
|
||||||
</staticText>
|
</staticText>
|
||||||
<staticText>
|
<staticText>
|
||||||
<reportElement x="358" y="0" width="100" height="24" uuid="9eddb29b-3024-4f0d-90f5-e8e896add7c0">
|
<reportElement x="358" y="0" width="97" height="24" uuid="9eddb29b-3024-4f0d-90f5-e8e896add7c0">
|
||||||
<property name="com.jaspersoft.studio.spreadsheet.connectionID" value="df75863b-fbfb-4332-a9fa-dbacf818e85c"/>
|
<property name="com.jaspersoft.studio.spreadsheet.connectionID" value="df75863b-fbfb-4332-a9fa-dbacf818e85c"/>
|
||||||
</reportElement>
|
</reportElement>
|
||||||
<textElement verticalAlignment="Middle">
|
<textElement verticalAlignment="Middle">
|
||||||
@@ -84,7 +86,7 @@
|
|||||||
<text><![CDATA[Žadatel]]></text>
|
<text><![CDATA[Žadatel]]></text>
|
||||||
</staticText>
|
</staticText>
|
||||||
<staticText>
|
<staticText>
|
||||||
<reportElement x="460" y="0" width="40" height="24" uuid="783dc31a-7f32-44d1-b455-6e8d25d5a943">
|
<reportElement x="451" y="0" width="45" height="24" uuid="783dc31a-7f32-44d1-b455-6e8d25d5a943">
|
||||||
<property name="com.jaspersoft.studio.spreadsheet.connectionID" value="ef5d98d4-a0b8-4098-be82-3ea9a1bc2213"/>
|
<property name="com.jaspersoft.studio.spreadsheet.connectionID" value="ef5d98d4-a0b8-4098-be82-3ea9a1bc2213"/>
|
||||||
</reportElement>
|
</reportElement>
|
||||||
<textElement verticalAlignment="Middle">
|
<textElement verticalAlignment="Middle">
|
||||||
@@ -155,7 +157,7 @@
|
|||||||
<textFieldExpression><![CDATA[$F{bill.requirement.to}]]></textFieldExpression>
|
<textFieldExpression><![CDATA[$F{bill.requirement.to}]]></textFieldExpression>
|
||||||
</textField>
|
</textField>
|
||||||
<textField>
|
<textField>
|
||||||
<reportElement x="358" y="1" width="100" height="12" uuid="3a197226-28d7-4384-b74a-12e748bd0967">
|
<reportElement x="358" y="1" width="97" height="12" uuid="3a197226-28d7-4384-b74a-12e748bd0967">
|
||||||
<property name="com.jaspersoft.studio.spreadsheet.connectionID" value="df75863b-fbfb-4332-a9fa-dbacf818e85c"/>
|
<property name="com.jaspersoft.studio.spreadsheet.connectionID" value="df75863b-fbfb-4332-a9fa-dbacf818e85c"/>
|
||||||
</reportElement>
|
</reportElement>
|
||||||
<textElement>
|
<textElement>
|
||||||
@@ -164,7 +166,7 @@
|
|||||||
<textFieldExpression><![CDATA[$F{bill.ownedBy}]]></textFieldExpression>
|
<textFieldExpression><![CDATA[$F{bill.ownedBy}]]></textFieldExpression>
|
||||||
</textField>
|
</textField>
|
||||||
<textField pattern="###0.00;-###0.00">
|
<textField pattern="###0.00;-###0.00">
|
||||||
<reportElement x="460" y="1" width="40" height="12" uuid="02a5e327-b7ab-4841-a895-0d285770e3c8">
|
<reportElement x="451" y="1" width="45" height="12" uuid="02a5e327-b7ab-4841-a895-0d285770e3c8">
|
||||||
<property name="com.jaspersoft.studio.spreadsheet.connectionID" value="ef5d98d4-a0b8-4098-be82-3ea9a1bc2213"/>
|
<property name="com.jaspersoft.studio.spreadsheet.connectionID" value="ef5d98d4-a0b8-4098-be82-3ea9a1bc2213"/>
|
||||||
</reportElement>
|
</reportElement>
|
||||||
<textElement textAlignment="Right">
|
<textElement textAlignment="Right">
|
||||||
|
|||||||
Binary file not shown.
@@ -1,7 +1,9 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<!-- Created with Jaspersoft Studio version 6.6.0.final using JasperReports Library version 6.6.0 -->
|
|
||||||
<jasperReport xmlns="http://jasperreports.sourceforge.net/jasperreports" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports http://jasperreports.sourceforge.net/xsd/jasperreport.xsd" name="TripBills" pageWidth="595" pageHeight="842" columnWidth="555" leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20" uuid="b63eddc4-7326-45c4-99b4-fc35d6e98179">
|
<jasperReport xmlns="http://jasperreports.sourceforge.net/jasperreports" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports http://jasperreports.sourceforge.net/xsd/jasperreport.xsd" name="TripBills" pageWidth="595" pageHeight="842" columnWidth="555" leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20" uuid="b63eddc4-7326-45c4-99b4-fc35d6e98179">
|
||||||
<property name="com.jaspersoft.studio.data.defaultdataadapter" value="One Empty Record"/>
|
<property name="com.jaspersoft.studio.data.defaultdataadapter" value="One Empty Record"/>
|
||||||
|
<property name="ireport.zoom" value="1.4641000000000006"/>
|
||||||
|
<property name="ireport.x" value="0"/>
|
||||||
|
<property name="ireport.y" value="0"/>
|
||||||
<queryString>
|
<queryString>
|
||||||
<![CDATA[]]>
|
<![CDATA[]]>
|
||||||
</queryString>
|
</queryString>
|
||||||
@@ -19,7 +21,7 @@
|
|||||||
<title>
|
<title>
|
||||||
<band height="23" splitType="Stretch">
|
<band height="23" splitType="Stretch">
|
||||||
<staticText>
|
<staticText>
|
||||||
<reportElement x="203" y="0" width="237" height="20" uuid="bc6cd7eb-bb1a-4114-b37d-ac64e951ca84"/>
|
<reportElement x="0" y="0" width="552" height="20" uuid="bc6cd7eb-bb1a-4114-b37d-ac64e951ca84"/>
|
||||||
<textElement textAlignment="Center">
|
<textElement textAlignment="Center">
|
||||||
<font size="14" isBold="true" pdfFontName="Helvetica-Bold" pdfEncoding="Cp1250" isPdfEmbedded="true"/>
|
<font size="14" isBold="true" pdfFontName="Helvetica-Bold" pdfEncoding="Cp1250" isPdfEmbedded="true"/>
|
||||||
</textElement>
|
</textElement>
|
||||||
|
|||||||
@@ -9,10 +9,17 @@
|
|||||||
<security:authentication-provider ref="adAuthProvider"/>
|
<security:authentication-provider ref="adAuthProvider"/>
|
||||||
</security:authentication-manager>
|
</security:authentication-manager>
|
||||||
|
|
||||||
<bean id="adAuthProvider" class="org.springframework.security.ldap.authentication.ad.ActiveDirectoryLdapAuthenticationProvider">
|
<!--<bean id="adAuthProvider" class="org.springframework.security.ldap.authentication.ad.ActiveDirectoryLdapAuthenticationProvider">
|
||||||
<constructor-arg name="domain" value="${ad.domain}"/>
|
<constructor-arg name="domain" value="${ad.domain}"/>
|
||||||
<constructor-arg name="url" value="${ad.ldapUrl}"/>
|
<constructor-arg name="url" value="${ad.ldapUrl}"/>
|
||||||
<property name="userDetailsContextMapper" ref="adUserMapper"/>
|
<property name="userDetailsContextMapper" ref="adUserMapper"/>
|
||||||
|
</bean>-->
|
||||||
|
|
||||||
|
<bean id="adAuthProvider" class="info.bukova.isspst.security.AdAuthenticationProvider">
|
||||||
|
<constructor-arg name="domain" value="${ad.domain}"/>
|
||||||
|
<constructor-arg name="upnSuffix" value="${ad.upnSuffix}"/>
|
||||||
|
<constructor-arg name="url" value="${ad.ldapUrl}"/>
|
||||||
|
<property name="userDetailsContextMapper" ref="adUserMapper"/>
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
<bean id="adUserMapper" class="info.bukova.isspst.services.users.AdUserCtxMapper">
|
<bean id="adUserMapper" class="info.bukova.isspst.services.users.AdUserCtxMapper">
|
||||||
|
|||||||
@@ -51,6 +51,6 @@
|
|||||||
<div id="mainData">
|
<div id="mainData">
|
||||||
<u:include src="${gridZul}" />
|
<u:include src="${gridZul}" />
|
||||||
</div>
|
</div>
|
||||||
<div id="footer"> Verze 4.2 </div>
|
<div id="footer"> Verze 4.4 </div>
|
||||||
</div>
|
</div>
|
||||||
</html>
|
</html>
|
||||||
@@ -205,7 +205,14 @@
|
|||||||
<label value="${labels.RequirementInvoicedAmount}"/>
|
<label value="${labels.RequirementInvoicedAmount}"/>
|
||||||
<label value="@load(vm.invoicedAmount) @converter(vm.bigDecimalConverter)"/>
|
<label value="@load(vm.invoicedAmount) @converter(vm.bigDecimalConverter)"/>
|
||||||
</hbox>
|
</hbox>
|
||||||
|
<hbox visible="@load(not empty vm.workgroupLimit)">
|
||||||
|
<label value="Limit komise "/>
|
||||||
|
<label value="@load(vm.dataBean.workgroup)"/>
|
||||||
|
<label value=" / vyčerpáno: "/>
|
||||||
|
<label value="@load(vm.workgroupLimit) @converter(vm.bigDecimalConverter)"/>
|
||||||
|
<label value=" / "/>
|
||||||
|
<label value="@load(vm.workgroupInvoiced) @converter(vm.bigDecimalConverter)"/>
|
||||||
|
</hbox>
|
||||||
</vbox>
|
</vbox>
|
||||||
</div>
|
</div>
|
||||||
</hbox>
|
</hbox>
|
||||||
|
|||||||
@@ -247,7 +247,7 @@
|
|||||||
<listcell label="@load(each.bill.total) @converter(vm.standardBigDecimalConverter)"/>
|
<listcell label="@load(each.bill.total) @converter(vm.standardBigDecimalConverter)"/>
|
||||||
<listcell label="@load(each.bill.ownedBy)"/>
|
<listcell label="@load(each.bill.ownedBy)"/>
|
||||||
<listcell label="@load(each.bill.ownedBy ne each.bill.requirement.ownedBy) @converter(vm.standardBoolConverter)"/>
|
<listcell label="@load(each.bill.ownedBy ne each.bill.requirement.ownedBy) @converter(vm.standardBoolConverter)"/>
|
||||||
<listcell label="@load(each.lastApproveDate) @converter('formatedDate', format=labels.DateFormat)"/>
|
<listcell label="@load(each.approveDate) @converter('formatedDate', format=labels.DateFormat)"/>
|
||||||
<listcell label="@load(each.bill.paid) @converter(vm.standardBoolConverter)"/>
|
<listcell label="@load(each.bill.paid) @converter(vm.standardBoolConverter)"/>
|
||||||
<listcell label="@load(each.bill.paidDate) @converter('formatedDate', format=labels.DateFormat)"/>
|
<listcell label="@load(each.bill.paidDate) @converter('formatedDate', format=labels.DateFormat)"/>
|
||||||
</listitem>
|
</listitem>
|
||||||
|
|||||||
Reference in New Issue
Block a user