package nc.service.rest.utils;

import java.util.Set;
import java.util.Map;
import java.util.List;
import java.util.ArrayList;
import java.util.Collection;
import java.util.stream.Collectors;
import java.util.HashMap;
import java.util.HashSet;
import nc.bs.dao.BaseDAO;
import nc.bs.framework.common.NCLocator;
import nc.jdbc.framework.processor.MapListProcessor;
import nc.vo.bd.currtype.CurrtypeVO;
import nc.vo.bd.meta.IBDObject;
import nc.vo.bd.vouchertype.VoucherTypeVO;
import nc.vo.gl.pubvoucher.DetailVO;
import nc.vo.gl.pubvoucher.VoucherVO;
import nc.vo.glcom.ass.AssVO;
import nc.vo.org.AccountingBookVO;
import nc.vo.org.CorpVO;
import nc.vo.org.GroupVO;
import nc.vo.org.OrgVO;
import nc.vo.sm.UserVO;
import nc.vo.pub.BusinessException;
import nc.vo.pub.lang.UFDate;
import nc.vo.vorg.CorpVersionVO;
import nc.vo.vorg.OrgVersionVO;
import nccloud.pubitf.gl.lightgl.voucher.IVoucherWebQryService;

/**
 * <b> NCC-NC推送凭证：VO翻译工具类 </b>
 * 2020-11-18
 * @version NCC2005
 */
public class TranslateVoucherUtil {

	private static class DaoHolder {
		public final static BaseDAO dao = new BaseDAO(); // BaseDAO只new一次
	}

	public BaseDAO getDao() {
		return DaoHolder.dao;
	}

	public TranslateVoucherUtil() { }

	/**
	 * 编码翻译成主键
	 * 
	 * @param vos
	 * @throws BusinessException
	 */
	public void translateCode2Key(List<VoucherVO> vos) throws BusinessException {
		translate(vos, 1);
	}

	/**
	 * 主键翻译成编码
	 * 
	 * @param vos
	 * @throws BusinessException
	 */
	public void translateKey2Code(List<VoucherVO> vos) throws BusinessException {
		translate(vos, 2);
	}

	/**
	 * 翻译
	 * 
	 * @param vos
	 * @param derection 1:编码翻译成主键；2:主键翻译成编码
	 */
	public void translate(List<VoucherVO> vos, int derection) throws BusinessException {
		if (vos == null || vos.size() == 0) {
			return;
		}
		translateHead(vos, derection); // 表头字段翻译
		translateBody(vos, derection); // 表体字段翻译
	}

	/**
	 * 表头字段翻译
	 * 
	 * @param vos
	 * @param derection 1:编码翻译成主键；2:主键翻译成编码
	 * @throws BusinessException
	 */
	public void translateHead(List<VoucherVO> vos, int derection) throws BusinessException {
		// 1. 表头需要翻译的主键或编码集合
		Set<String> groupSet = new HashSet<String>();
		Set<String> orgSet = new HashSet<String>();
		Set<String> orgvSet = new HashSet<String>();
		Set<String> systemSet = new HashSet<String>();
		Set<String> accbookSet = new HashSet<String>();
		Set<String> vtypeSet = new HashSet<String>();
		Set<String> userSet = new HashSet<String>();

		// 2.收集需要翻译的编码或主键集合
		for (VoucherVO vo : vos) {
			groupSet.add(vo.getPk_group());
			orgSet.add(vo.getPk_org());
			orgvSet.add(vo.getPk_org_v());
			systemSet.add(vo.getPk_system());
			accbookSet.add(vo.getPk_accountingbook());
			vtypeSet.add(vo.getPk_vouchertype());

			userSet.add(vo.getPk_prepared()); // 制单人
			userSet.add(vo.getPk_checked()); // 审核人
			userSet.add(vo.getPk_manager()); // 记账人
			userSet.add(vo.getModifier()); // 修改人
		}

		// 3.翻译
		Map<String, String> groupMap = transGroup(groupSet, derection);
		Map<String, String> orgMap = transOrg(orgSet, derection);
		Map<String, String> orgvMap = transOrgVersion(orgvSet, derection);
		Map<String, String> accbookMap = transAccBook(accbookSet, derection);
		Map<String, String> vtypeMap = transVoucherType(vtypeSet, derection);
		Map<String, String> userMap = transUser(userSet, derection);

		// 4.翻译结果设置到VO字段上
		for (VoucherVO vo : vos) {
			vo.setPk_group(groupMap.get(vo.getPk_group()));
			vo.setPk_org(orgMap.get(vo.getPk_org()));
			vo.setPk_org_v(orgvMap.get(vo.getPk_org_v()));

			String pk_accbook = accbookMap.get(vo.getPk_accountingbook());
			if (pk_accbook == null) {
				throw new BusinessException("核算账簿【" + vo.getPk_accountingbook() + "】无法翻译");
			}
			vo.setPk_accountingbook(pk_accbook);
			vo.setPk_vouchertype(vtypeMap.get(vo.getPk_vouchertype()));
			vo.setPk_prepared(userMap.get(vo.getPk_prepared()));
			vo.setPk_checked(userMap.get(vo.getPk_checked()));
			vo.setPk_manager(userMap.get(vo.getPk_manager()));
			vo.setModifier(userMap.get(vo.getModifier()));
		}
	}

	/**
	 * 表体字段翻译
	 * 
	 * @param vos
	 * @param derection 1:编码翻译成主键；2:主键翻译成编码
	 * @throws BusinessException
	 */
	public void translateBody(List<VoucherVO> vos, int derection) throws BusinessException {

		// 1. 表体需要翻译的主键或编码集合
		Set<String> accasoaSet = new HashSet<String>();
		Set<String> currtypeSet = new HashSet<String>();
		Set<String> unitSet = new HashSet<String>();
		Set<String> unitvSet = new HashSet<String>();

		// 2.收集需要翻译的编码或主键集合
		String accasoaTableCode = null; // NC63科目表编码
		String pk_accbook = null; // 核算账簿
		for (VoucherVO vo : vos) {
			DetailVO[] dvos = vo.getDetails();
			if (dvos == null || dvos.length == 0) {
				continue;
			}
			if (accasoaTableCode == null) {
				accasoaTableCode = vo.getFree5(); // 科目表编码
			}
			if (pk_accbook == null) {
				pk_accbook = vo.getPk_accountingbook();
			}
			for (DetailVO dvo : dvos) {
				accasoaSet.add(dvo.getPk_accasoa());
				currtypeSet.add(dvo.getPk_currtype());
				unitSet.add(dvo.getPk_unit());
				unitvSet.add(dvo.getPk_unit_v());
			}
		}

		// 3.翻译
		Map<String, String> accasoaMap = transAccasoa(pk_accbook, accasoaTableCode, accasoaSet, derection);
		Map<String, String> currtypeMap = transCurrType(currtypeSet, derection);
		Map<String, String> unitMap = transUnit(unitSet, derection);
		Map<String, String> unitvMap = transUnitVersion(unitvSet, derection);

		// 4.翻译结果设置到VO字段上
		for (VoucherVO vo : vos) {
			DetailVO[] dvos = vo.getDetails();
			if (dvos == null || dvos.length == 0) {
				continue;
			}
			for (DetailVO dvo : dvos) {
				dvo.setPk_group(vo.getPk_group());
				dvo.setPk_org(vo.getPk_org());
				dvo.setPk_org_v(vo.getPk_org_v());
				dvo.setPk_accountingbook(vo.getPk_accountingbook());
				dvo.setPk_vouchertype(vo.getPk_vouchertype());

				String pk_accasoa = accasoaMap.get(dvo.getPk_accasoa()); // 会计科目
				if (pk_accasoa == null) {
					throw new BusinessException("会计科目【" + dvo.getPk_accasoa() + "】无法翻译");
				}
				dvo.setPk_accasoa(pk_accasoa);

				dvo.setPk_currtype(currtypeMap.get(dvo.getPk_currtype()));
				dvo.setPk_unit(unitMap.get(dvo.getPk_unit()));
				dvo.setPk_unit_v(unitvMap.get(dvo.getPk_unit_v()));
				if (derection == 1) { // 编码翻译主键时需要翻译辅助核算
					String pk_org = vo.getPk_org();
					String pk_accountingbook = vo.getPk_accountingbook(); // 核算账簿
					UFDate preparedDate = dvo.getPrepareddate(); // 制单日期
					if (preparedDate == null || preparedDate.toString().length() < 10) {
						throw new BusinessException("制单日期【prepareddate】字段值错误");
					}
					String preparedDateStr = preparedDate.toString().substring(0, 10); // 制单日期(字符串)
					String assid = translateAssVOs(pk_org, pk_accountingbook, pk_accasoa, preparedDateStr,
							dvo.getAss()); // 翻译辅助属性VO，并返回assid
					dvo.setAssid(assid);
				}
			}
		}
	}

	/**
	 * 辅助核算VO翻译
	 * 
	 * @param pk_org
	 * @param pk_accountingbook
	 * @param pk_accasoa
	 * @param prepareddate
	 * @param assVOs
	 * @return
	 * @throws BusinessException
	 */
	public String translateAssVOs(String pk_org, String pk_accountingbook, String pk_accasoa, String prepareddate,
			AssVO[] assVOs) throws BusinessException {

		Set<String> accassItemCodeSet = new HashSet<String>(); // 辅助核算项目编码
		// 辅助核算所选值编码集合，按辅助核算项目分组：key:辅助核算项目编码, value:辅助核算值编码集合
		Map<String, Set<String>> accassCodeMap = new HashMap<String, Set<String>>();

		assVOs = assVOs == null ? new AssVO[0] : assVOs;
		// 1.收集翻译字段值
		for (AssVO avo : assVOs) {
			accassItemCodeSet.add(avo.getChecktypecode()); // 辅助核算项目
			if (accassCodeMap.containsKey(avo.getChecktypecode())) {
				Set<String> codeSet = accassCodeMap.get(avo.getChecktypecode());
				codeSet.add(avo.getCheckvaluecode());
			} else {
				Set<String> codeSet = new HashSet<String>();
				codeSet.add(avo.getCheckvaluecode());
				accassCodeMap.put(avo.getChecktypecode(), codeSet);
			}
		}

		// 2.翻译辅助核算项目
		Map<String, Map<String, String>> itemTrnasRes = transAccassItemCode(accassItemCodeSet);

		// 3.翻译辅助核算所选值编码
		Map<String, String> codeTransResult = new HashMap<String, String>(); // 翻译结果
		for (String accItemCode : accassCodeMap.keySet()) {
			String classid = itemTrnasRes.get(accItemCode) == null ? null
					: itemTrnasRes.get(accItemCode).get("classid");
			Set<String> codes = accassCodeMap.get(accItemCode);
			codeTransResult.putAll(transCode2KeyByClassID(classid, pk_org, codes));
		}

		// 4.将翻译结果设置到VO上
		for (AssVO avo : assVOs) {
			Map<String, String> assItemMap = itemTrnasRes.get(avo.getChecktypecode());
			if (assItemMap == null || !assItemMap.containsKey("pk") || !assItemMap.containsKey("classid")) {
				throw new BusinessException("辅助核算项目【" + avo.getChecktypecode() + "】无法翻译");
			}
			avo.setChecktypecode(assItemMap.get("ncc_code"));
			avo.setPk_Checktype(assItemMap.get("pk"));
			avo.setM_classid(assItemMap.get("classid"));
			avo.setPk_Checkvalue(codeTransResult.get(avo.getCheckvaluecode()));
		}

		// 5.获取assid
		List<Map<String, Object>> assMap = new ArrayList<Map<String, Object>>();
		for (int i = 0; i < assVOs.length; i++) {
			Map<String, Object> params = new HashMap<String, Object>();
			params.put("checktypecode", assVOs[i].getChecktypecode()); // 辅助核算项目编码
			params.put("pk_Checktype", assVOs[i].getPk_Checktype()); // 辅助核算项目主键
			params.put("pk_accassitem", assVOs[i].getPk_Checktype()); // 辅助核算项目主键
			params.put("checktypename", "~"); // 辅助核算项目名称；这里其实不需要这个值，不传的话接口报NPE；
			params.put("m_classid", assVOs[i].getM_classid()); // m_classid
			params.put("classid", assVOs[i].getM_classid()); // classid
			params.put("key", i + ".0"); // key

			List<String> valueList = new ArrayList<String>(); // 辅助核算主键List
			List<String> codeList = new ArrayList<String>(); // 辅助核算编码List

			valueList.add(assVOs[i].getPk_Checkvalue());
			codeList.add(assVOs[i].getCheckvaluecode());

			params.put("pk_Checkvalue", valueList);
			params.put("checkvaluecode", codeList);
			assMap.add(params);
		}

		IVoucherWebQryService service = NCLocator.getInstance().lookup(IVoucherWebQryService.class);
		List<Map<String, Object>> queryResult = null;
		try {
			queryResult = service.queryAssIds(pk_accountingbook, pk_accasoa, prepareddate, assMap);
		} catch (Exception e) {
			throw new BusinessException("NCC的科目和辅助核算关联关系跟NC63不一致，请检查配置");
		}
		
		Object assid = null;
		if (queryResult == null || queryResult.size() != 1) {
			assid = null;
		} else {
			assid = queryResult.get(0).get("assid");
		}
		return assid == null ? null : assid.toString();
	}

	/**
	 * pk_group 字段翻译
	 * 
	 * @param params
	 * @param derection 1:编码翻译成主键；2:主键翻译成编码
	 * @return
	 * @throws BusinessException
	 */
	@SuppressWarnings("unchecked")
	public Map<String, String> transGroup(Set<String> params, int derection) throws BusinessException {
		String whereSql = derection == 1 ? " code " : " pk_group ";
		whereSql = whereSql + " in (" + createInSql(params) + ")";
		Collection<GroupVO> vos = getDao().retrieveByClause(GroupVO.class, whereSql);

		Map<String, String> result = new HashMap<String, String>();
		if (vos == null || vos.size() == 0) {
			return result;
		}
		for (GroupVO vo : vos) {
			String key = derection == 1 ? vo.getCode() : vo.getPk_group();
			String value = derection == 1 ? vo.getPk_group() : vo.getCode();
			result.put(key, value);
		}
		return result;
	}

	/**
	 * pk_org字段翻译
	 * 
	 * @param pkOrCode
	 * @param derection 1:编码翻译成主键；2:主键翻译成编码
	 * @return
	 * @throws BusinessException
	 */
	@SuppressWarnings("unchecked")
	public Map<String, String> transOrg(Set<String> params, int derection) throws BusinessException {
		String whereSql = derection == 1 ? " code " : " pk_org ";
//		whereSql = whereSql + " in (" + createInSql(params) + ")";
		whereSql = whereSql + " in (" + createInSql(params) + ") and isbusinessunit ='Y'";

		Collection<OrgVO> vos = getDao().retrieveByClause(OrgVO.class, whereSql);

		Map<String, String> result = new HashMap<String, String>();
		if (vos == null || vos.size() == 0) {
			return result;
		}
		for (OrgVO vo : vos) {
			String key = derection == 1 ? vo.getCode() : vo.getPk_org();
			String value = derection == 1 ? vo.getPk_org() : vo.getCode();
			result.put(key, value);
		}
		return result;
	}

	/**
	 * pk_org_v字段翻译
	 * 
	 * @param params
	 * @param derection 1:编码翻译成主键；2:主键翻译成编码
	 * @return
	 * @throws BusinessException
	 */
	@SuppressWarnings("unchecked")
	public Map<String, String> transOrgVersion(Set<String> params, int derection) throws BusinessException {
		String whereSql = derection == 1 ? " code " : " pk_vid ";
		whereSql = whereSql + " in (" + createInSql(params) + ")";
		Collection<OrgVersionVO> vos = getDao().retrieveByClause(OrgVersionVO.class, whereSql);

		Map<String, String> result = new HashMap<String, String>();
		if (vos == null || vos.size() == 0) {
			return result;
		}
		for (OrgVersionVO vo : vos) {
			String key = derection == 1 ? vo.getCode() : vo.getPk_vid();
			String value = derection == 1 ? vo.getPk_vid() : vo.getCode();
			result.put(key, value);
		}
		return result;
	}

	/**
	 * pk_accountingbook字段翻译
	 * 
	 * @param params
	 * @param derection 1:编码翻译成主键；2:主键翻译成编码
	 * @return
	 * @throws BusinessException
	 */
	@SuppressWarnings("unchecked")
	public Map<String, String> transAccBook(Set<String> params, int derection) throws BusinessException {
		String whereSql = derection == 1 ? " code " : " pk_accountingbook ";
		whereSql = whereSql + " in (" + createInSql(params) + ")";
		Collection<AccountingBookVO> vos = getDao().retrieveByClause(AccountingBookVO.class, whereSql);

		Map<String, String> result = new HashMap<String, String>();
		if (vos == null || vos.size() == 0) {
			return result;
		}
		for (AccountingBookVO vo : vos) {
			String key = derection == 1 ? vo.getCode() : vo.getPk_accountingbook();
			String value = derection == 1 ? vo.getPk_accountingbook() : vo.getCode();
			result.put(key, value);
		}
		return result;
	}

	/**
	 * pk_vouchertype 字段翻译
	 * 
	 * @param params
	 * @param derection 1:编码翻译成主键；2:主键翻译成编码
	 * @return
	 * @throws BusinessException
	 */
	@SuppressWarnings("unchecked")
	public Map<String, String> transVoucherType(Set<String> params, int derection) throws BusinessException {
		String whereSql = derection == 1 ? " code " : " pk_vouchertype ";
		whereSql = whereSql + " in (" + createInSql(params) + ")";
		Collection<VoucherTypeVO> vos = getDao().retrieveByClause(VoucherTypeVO.class, whereSql);

		Map<String, String> result = new HashMap<String, String>();
		if (vos == null || vos.size() == 0) {
			return result;
		}
		for (VoucherTypeVO vo : vos) {
			String key = derection == 1 ? vo.getCode() : vo.getPk_vouchertype();
			String value = derection == 1 ? vo.getPk_vouchertype() : vo.getCode();
			result.put(key, value);
		}
		return result;
	}
	
	/**
	 * 用户翻译
	 * 
	 * @param params
	 * @param derection
	 * @return
	 * @throws BusinessException
	 */
	@SuppressWarnings("unchecked")
	public Map<String, String> transUser(Set<String> params, int derection) throws BusinessException {
		String whereSql = derection == 1 ? " user_code " : " cuserid ";
		whereSql = whereSql + " in (" + createInSql(params) + ")";
		Collection<UserVO> vos = getDao().retrieveByClause(UserVO.class, whereSql);

		Map<String, String> result = new HashMap<String, String>();
		if (vos == null || vos.size() == 0) {
			return result;
		}
		for (UserVO vo : vos) {
			String key = derection == 1 ? vo.getUser_code() : vo.getCuserid();
			String value = derection == 1 ? vo.getCuserid() : vo.getUser_code();
			result.put(key, value);
		}
		return result;
	}

	/**
	 * pk_accasoa 字段翻译
	 * 
	 * @param pk_accbook
	 * @param accasoaTableCode
	 * @param codes NC会计科目编码
	 * @param derection
	 * @return
	 * @throws BusinessException
	 */
	@SuppressWarnings("unchecked")
	public Map<String, String> transAccasoa(String pk_accbook, String accasoaTableCode, Set<String> codes,
			int derection) throws BusinessException {
		Map<String, String> result = new HashMap<String, String>();
		if (codes == null || codes.size() == 0) {
			return result;
		}
		String sql = null;
		Map<String, String> codeMap = new HashMap<String, String>(); // NC编码翻译成NCC编码，key=NCC编码，value=NC编码
		if (derection == 1) {
			if (pk_accbook == null || accasoaTableCode == null) {
				throw new BusinessException("账簿和科目体系编码为空，科目无法翻译");
			}
			codeMap = transNCAccCode2NccCode(accasoaTableCode, codes);
			Set<String> nccCodeSet = codeMap.keySet(); // NCC编码
			// 2.NCC科目编码翻译成主键：通过账簿找科目体系，然后根据体系编码和科目编码查询主键
			sql = "select acc.code, accasoa.pk_accasoa from bd_account acc left join bd_accasoa accasoa "
					+ " on acc.pk_account = accasoa.pk_account left join bd_accchart accchart on "
					+ " accasoa.pk_accchart = accchart.pk_accchart where accchart.pk_accchart in "
					+ " (select pk_curraccchart from org_accountingbook where pk_accountingbook='" + pk_accbook + "')"
					+ " and acc.code in (" + createInSql(nccCodeSet) + ")";
		} else {
			// 科目主键翻译成编码
			sql = "select accasoa.pk_accasoa,acc.code from bd_accasoa accasoa left join bd_account acc on "
					+ "accasoa.pk_account = acc.pk_account where accasoa.pk_accasoa in (" + createInSql(codes) + ")";
		}

		List<Map<String, String>> data = (List<Map<String, String>>) getDao().executeQuery(sql, new MapListProcessor());
		if (data == null || data.size() == 0) {
			return result;
		}
		for (int i = 0; i < data.size(); i++) {
			Map<String, String> dataMap = data.get(i);
			String key = dataMap.get(derection == 1 ? "code" : "pk_accasoa");
			if (derection == 1) {
				key = codeMap.get(key); // NCC编码翻译成NC的科目编码
			}
			String value = dataMap.get(derection == 1 ? "pk_accasoa" : "code");
			result.put(key, value);
		}
		return result;
	}
	
	/**
	 * NC会计科目编码翻译成NCC编码
	 * 
	 * @param accasoaTableCode NC科目体系表编码
	 * @param codes NC科目编码
	 * @return Map:key=NCC科目编码，value=NC科目编码
	 * @throws BusinessException
	 */
	@SuppressWarnings("unchecked")
	public Map<String, String> transNCAccCode2NccCode(String accasoaTableCode, Set<String> codes)
			throws BusinessException {
		String sql = "select factorvalue1 as nc_code, factorvalue3 as ncc_code from fip_docview_b where "
				+ " pk_classview in (select pk_classview from fip_docview where viewcode = 'WYZZ003') "
				+ " and factorvalue2 = '" + accasoaTableCode + "' and factorvalue1 in (" + createInSql(codes) + ")";

		List<Map<String, String>> data = (List<Map<String, String>>) getDao().executeQuery(sql, new MapListProcessor());

		Map<String, String> result = new HashMap<String, String>();
		if (data == null || data.size() == 0) {
			return result;
		}
		for (int i = 0; i < data.size(); i++) {
			Map<String, String> map = data.get(i);
			result.put(map.get("ncc_code"), map.get("nc_code"));
		}
		return result;
	}

	/**
	 * pk_currtype 字段翻译
	 * 
	 * @param params
	 * @param derection 1:编码翻译成主键；2:主键翻译成编码
	 * @return
	 * @throws BusinessException
	 */
	@SuppressWarnings("unchecked")
	public Map<String, String> transCurrType(Set<String> params, int derection) throws BusinessException {
		String whereSql = derection == 1 ? " code " : " pk_currtype ";
		whereSql = whereSql + " in (" + createInSql(params) + ")";
		Collection<CurrtypeVO> vos = getDao().retrieveByClause(CurrtypeVO.class, whereSql);

		Map<String, String> result = new HashMap<String, String>();
		if (vos == null || vos.size() == 0) {
			return result;
		}
		for (CurrtypeVO vo : vos) {
			String key = derection == 1 ? vo.getCode() : vo.getPk_currtype();
			String value = derection == 1 ? vo.getPk_currtype() : vo.getCode();
			result.put(key, value);
		}
		return result;
	}

	/**
	 * pk_unit 字段翻译
	 * 
	 * @param params
	 * @param derection 1:编码翻译成主键；2:主键翻译成编码
	 * @return
	 * @throws BusinessException
	 */
	@SuppressWarnings("unchecked")
	public Map<String, String> transUnit(Set<String> params, int derection) throws BusinessException {
		String whereSql = derection == 1 ? " code " : " pk_corp ";
		whereSql = whereSql + " in (" + createInSql(params) + ")";
		Collection<CorpVO> vos = getDao().retrieveByClause(CorpVO.class, whereSql);

		Map<String, String> result = new HashMap<String, String>();
		if (vos == null || vos.size() == 0) {
			return result;
		}
		for (CorpVO vo : vos) {
			String key = derection == 1 ? vo.getCode() : vo.getPk_corp();
			String value = derection == 1 ? vo.getPk_corp() : vo.getCode();
			result.put(key, value);
		}
		return result;
	}

	/**
	 * pk_unit_v 字段翻译
	 * 
	 * @param params
	 * @param derection 1:编码翻译成主键；2:主键翻译成编码
	 * @return
	 * @throws BusinessException
	 */
	@SuppressWarnings("unchecked")
	public Map<String, String> transUnitVersion(Set<String> params, int derection) throws BusinessException {
		String whereSql = derection == 1 ? " code " : " pk_vid ";
		whereSql = whereSql + " in (" + createInSql(params) + ")";
		Collection<CorpVersionVO> vos = getDao().retrieveByClause(CorpVersionVO.class, whereSql);

		Map<String, String> result = new HashMap<String, String>();
		if (vos == null || vos.size() == 0) {
			return result;
		}
		for (CorpVersionVO vo : vos) {
			String key = derection == 1 ? vo.getCode() : vo.getPk_vid();
			String value = derection == 1 ? vo.getPk_vid() : vo.getCode();
			result.put(key, value);
		}
		return result;
	}

	/**
	 * 辅助核算项目翻译
	 * 
	 * @param codes
	 * @return
	 * @throws BusinessException
	 */
	@SuppressWarnings("unchecked")
	public Map<String, Map<String, String>> transAccassItemCode(Set<String> codes) throws BusinessException {

		// 根据NCC对照表，先翻译成NCC编码，再翻译成NCC主键
		String sql = "select d.code as ncc_code, d.mnecode as nc_code,t.classid,t.pk_accassitem from bd_accassitem t left join "
				+ " bd_defdoc d on t.code = d.code where d.pk_defdoclist in (select pk_defdoclist from bd_defdoclist where  "
				+ " code = 'WYZZ001') and d.mnecode in (" + createInSql(codes) + ")";

		List<Map<String, String>> res = (List<Map<String, String>>) getDao().executeQuery(sql, new MapListProcessor());
		Map<String, Map<String, String>> result = new HashMap<String, Map<String, String>>();
		if (res == null || res.size() == 0) {
			return result;
		}
		for (Map<String, String> data : res) {
			String ncCode = data.get("nc_code");
			String nccCode = data.get("ncc_code");
			String pk = data.get("pk_accassitem");
			String classid = data.get("classid");

			Map<String, String> map = new HashMap<String, String>();
			map.put("pk", pk);
			map.put("classid", classid);
			map.put("ncc_code", nccCode);
			result.put(ncCode, map);
		}
		for (String code : codes) { // 校验是否有翻译失败的辅助核算项目
			if (!result.containsKey(code)) {
				throw new BusinessException("辅助核算项目【" + code + "】无法翻译");
			}
		}
		return result;
	}

	/**
	 * 根据classid和编码翻译辅助核算值
	 * 
	 * @param classid
	 * @param pk_org
	 * @param codes
	 * @return
	 * @throws BusinessException
	 */
	@SuppressWarnings("unchecked")
	public Map<String, String> transCode2KeyByClassID(String classid, String pk_org, Set<String> codes)
			throws BusinessException {
		Map<String, String> result = new HashMap<String, String>(); // 翻译结果：key:编码，value:主键
		if (classid == null) {
			throw new BusinessException("classid为空，无法翻译辅助核算");
		}
		if (codes == null || codes.size() == 0) {
			return result;
		}
		// 1.如果是部门档案，需要特殊处理(NCC部门def1字段为NC63部门编码)
		if ("b26fa3cb-4087-4027-a3b6-c83ab2a086a9".equals(classid)) {
			//modified by hanmh 2021-01-22 部门字段翻译使用自定义档案对照表，原有翻译逻辑先注释掉
			String sql = "SELECT  view_b.factorvalue2 as code,dept.pk_dept as pk_dept FROM fip_docview views  \r\n" + 
					"left join fip_docview_b view_b on views.pk_classview = view_b.pk_classview \r\n" + 
					"left join org_orgs org on view_b.factorvalue1 = org.code \r\n" + 
					"left join org_dept dept on view_b.factorvalue3 = dept.code \r\n" + 
					"where views.viewcode='WYZZ001' and dept.pk_org= '" + pk_org + "' and org.pk_org= '" + pk_org + "'"+
					" and view_b.factorvalue2 in (" + createInSql(codes)+ ")  \r\n" + 
					"and nvl(views.dr,0)=0 and nvl(view_b.dr,0)=0 and nvl(org.dr,0)=0 and nvl(dept.dr,0)=0 \r\n";
//			String sql = "select def1 as code,pk_dept from org_dept where def1 in (" + createInSql(codes)
//					+ ") and pk_org = '" + pk_org + "'";
			List<Map<String, String>> res = (List<Map<String, String>>) getDao().executeQuery(sql,
					new MapListProcessor());
			if (res == null || res.size() == 0) {
				return result;
			}
			for (Map<String, String> map : res) {
				String pk = map.get("pk_dept");
				String code = map.get("code");
				result.put(code, pk);
			}
			return result;
		}
		
		//wby 2021-10-12 如果是员工档案，需要特殊处理（NCC人员def3为NC63人员编码）
		if("40d39c26-a2b6-4f16-a018-45664cac1a1f".equals(classid)) {
			String sql = "select case when nvl(def3,'~')='~' then code else def3 end as code,pk_psndoc from bd_psndoc where enablestate=2 and code in (" + createInSql(codes) + ")";
			List<Map<String, String>> res = (List<Map<String, String>>) getDao().executeQuery(sql,
					new MapListProcessor());
			if (res == null || res.size() == 0) {
				return result;
			}
			for (Map<String, String> map : res) {
				String pk = map.get("pk_psndoc");
				String code = map.get("code");
				result.put(code, pk);
			}
			return result;
		}
		
		// 2.项目档案翻译添加组织过滤
		if ("2ee58f9b-781b-469f-b1d8-1816842515c3".equals(classid)) {
			String sql = "select project_code,pk_project from bd_project where project_code in (" + createInSql(codes)
					+ ") and pk_org = '" + pk_org + "'";
			List<Map<String, String>> res = (List<Map<String, String>>) getDao().executeQuery(sql,
					new MapListProcessor());
			if (res == null || res.size() == 0) {
				return result;
			}
			for (Map<String, String> map : res) {
				String pk = map.get("pk_project");
				String code = map.get("project_code");
				result.put(code, pk);
			}
			return result;
		}
		// 3. 其他档案翻译
		IBDObject[] objs = null;
		try {
			objs = TransIBDObjectUtil.transIBDObjectByCode(classid, codes.toArray(new String[0]));
		} catch (Exception e) {
			throw new BusinessException("翻译辅助核算值出错：" + e.getMessage());
		}
		if (objs == null) {
			return result;
		}
		for (IBDObject obj : objs) {
			String pk = obj.getId().toString();
			String code = obj.getCode().toString();
			result.put(code, pk);
		}
		return result;
	}

	/**
	 * Set集合：拼接SQL IN语句
	 * 
	 * @param paramsSet
	 * @return
	 */
	public String createInSql(Set<String> paramsSet) {
		if (paramsSet == null || paramsSet.size() == 0) {
			return "''";
		}
		paramsSet = paramsSet.stream().filter(param -> param != null).collect(Collectors.toSet()); // 过滤空值
		if (paramsSet.size() == 0) {
			return "''";
		}
		String[] array = paramsSet.toArray(new String[0]);
		StringBuffer inSql = new StringBuffer();
		for (int i = 0; i < array.length; i++) {
			inSql.append(i == array.length - 1 ? ("'" + array[i] + "'") : ("'" + array[i] + "',"));
		}
		return inSql.toString();
	}
	public static void main(String[] args) {
		Set<String> set = new HashSet<String>();
		set.add("1");
		set.add("3");
		set.add("2");
		set.add("1");
		set.add("5");
		set.add("6");
		System.out.println(set.size());
		
		for(String s:set) {
			System.out.println(s);
		}
	}
}
