package com.withiter.models.merchant; import java.util.ArrayList; import java.util.Date; import java.util.Iterator; import java.util.List; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import cn.bran.japid.util.StringUtils; import com.withiter.common.Constants; import com.withiter.common.Constants.ReservationStatus; import com.withiter.models.account.Reservation; /** * Haoma contains whole paidui information * * @author Cross * */ public class Haoma extends HaomaEntityDef { private static Logger logger = LoggerFactory.getLogger(Haoma.class); /** * Find Haoma by merchant id * * @param merchantId * id of merchant * @return */ public static Haoma findByMerchantId(String merchantId) { MorphiaQuery q = Haoma.q(); q.filter("merchantId", merchantId); if (q.first() != null) { return q.first(); } else { Haoma haoma = new Haoma(); haoma.merchantId = merchantId; haoma.initPaidui(); return haoma; } } /** * 初始化Paidui信息,enable=false; */ public void initPaidui() { logger.debug("initPaidui, merchant id : " + this.merchantId); Merchant m = Merchant.findByMid(this.merchantId); if (m == null) { logger.error("Merchant does not find!"); return; } String[] seatType = m.seatType; Paidui p = null; if (seatType == null) { return; } for (String i : seatType) { p = new Paidui(); this.haomaMap.put(Integer.parseInt(i), p); } } /** * 更新Paidui信息,enable=true; */ public void updatePaidui() { logger.debug("updatePaidui, merchant id : " + this.merchantId); Merchant m = Merchant.findByMid(this.merchantId); if (m == null) { logger.error("Merchant does not find!"); return; } String[] seatType = m.seatType; this.haomaMap.clear(); Paidui p = null; if (seatType == null) { return; } for (String i : seatType) { p = new Paidui(); p.enable = true; this.haomaMap.put(Integer.parseInt(i), p); } } /** * 重置Paidui信息,将所有排队号码重置为0 */ public void resetPaidui() { logger.debug("merchant id : " + this.merchantId); Merchant m = Merchant.findByMid(this.merchantId); if (m == null) { logger.error("Merchant does not find!"); return; } String[] seatType = m.seatType; Paidui p = null; if (seatType == null) { return; } for (String i : seatType) { p = new Paidui(); p.reset(); p.enable = true; this.haomaMap.put(Integer.parseInt(i), p); } } /** * 拿号(同步方法) * * @param accountId * 用户id * @param mid * 商家id * @param seatNumber * 座位数 * @return Reservation */ public synchronized static Reservation nahao(String accountId, String mid, int seatNumber, String tel) { Haoma haoma = Haoma.findByMerchantId(mid); Paidui paidui = haoma.haomaMap.get(seatNumber); paidui.enable = true; paidui.maxNumber += 1; haoma.save(); haoma.updateSelfForNahao(); Reservation reservation = new Reservation(); // 拿号时version和当前Haoma version一致 reservation.version = haoma.version; // 如果tel是空,说明是APP拿号。否则是现场手机拿号。 if (StringUtils.isEmpty(tel)) { reservation.accountId = accountId; } reservation.merchantId = mid; reservation.myNumber = paidui.maxNumber; reservation.seatNumber = seatNumber; reservation.status = ReservationStatus.active; reservation.valid = true; reservation.created = new Date(); reservation.modified = new Date(); reservation.save(); return reservation; } /** * 现场拿号失败,返回(同步方法) * @param reservation */ @Deprecated public synchronized static void nahaoRollback(Reservation reservation) { Haoma haoma = Haoma.findByMerchantId(reservation.merchantId); Paidui paidui = haoma.haomaMap.get(reservation.seatNumber); paidui.maxNumber -= 1; haoma.save(); reservation.valid = false; reservation.status = ReservationStatus.canceled; reservation.save(); } /** * 更新X人座位的finished, canceled, expired 数量 * * @param haoma * @param mid * @param myNumber * @param seatNumber * @param status * @return */ public synchronized static Haoma updateByXmethod(Haoma haoma, String mid, int myNumber, int seatNumber, ReservationStatus status) { Paidui p = haoma.haomaMap.get(seatNumber); switch (status) { case canceled: if (myNumber >= p.currentNumber) { p.canceled += 1; } break; case finished: p.currentNumber += 1; p.finished += 1; break; case expired: p.currentNumber += 1; p.expired += 1; break; } haoma.save(); return haoma; } public void updateSelf() { synchronized (Haoma.class) { logger.debug("start to Haoma.updateSelf"); Iterator ite = this.haomaMap.keySet().iterator(); while (ite.hasNext()) { Integer key = (Integer) ite.next(); Paidui p = this.haomaMap.get(key); if (!p.enable) { continue; } // if maxNumber > 0 and currentNumber == 0, then set // currentNumber to 1 if (p.maxNumber > 0 && p.currentNumber == 0) { p.currentNumber = 1; this.save(); } // check current number is valid or not, if not valid: current // number ++ // otherwise save current number. Reservation r = Reservation.queryForCancel(merchantId, key, p.currentNumber, this.version); if(r != null){ logger.debug("Reservation r = Reservation.queryForCancel(merchantId, key, p.currentNumber); - >" + "座位:"+r.seatNumber+", r.myNumber:"+r.myNumber+", r.valid:"+r.valid); } else { } while (r != null && !r.valid) { p.currentNumber += 1; this.save(); r = Reservation.queryForCancel(merchantId, key, p.currentNumber, this.version); } } // 检查是否需要排队 this.check(); } } public void updateSelfForNahao() { synchronized (Haoma.class) { Iterator ite = this.haomaMap.keySet().iterator(); while (ite.hasNext()) { Integer key = (Integer) ite.next(); Paidui p = this.haomaMap.get(key); if (!p.enable) { continue; } // if maxNumber > 0 and currentNumber == 0, then set // currentNumber to 1 if (p.maxNumber > 0 && p.currentNumber == 0) { p.currentNumber = 1; this.save(); } } // 检查是否需要排队 this.check(); } } /** * 清除排队信息(初始化) */ public static void clearPaidui() { MorphiaQuery q = Haoma.q(); long count = q.count(); List<Haoma> hList = new ArrayList<Haoma>(); long time = 0; int countPerPage = 10; if (count > 0) { if (count % 10 == 0) { time = count / 10; } else { time = count / 10 + 1; } for (int i = 0; i < time; i++) { hList = q.offset(i * countPerPage).limit(countPerPage).asList(); for (Haoma h : hList) { h.version += 1; h.resetPaidui(); h.save(); // set Reservation valid=false String mid = h.merchantId; MorphiaQuery qq = Reservation.q(); qq.filter("merchantId", mid).filter("valid", true); List<Reservation> rs = qq.asList(); if (rs != null) { for (Reservation r : rs) { r.valid = false; r.status = ReservationStatus.invalidByMerchantUpdate; r.save(); } } } } } } public void check() { Iterator it = this.haomaMap.keySet().iterator(); while (it.hasNext()) { Integer key = (Integer) it.next(); Paidui value = this.haomaMap.get(key); if (!value.enable) { continue; } // 不用排队条件: // 1. currentNumber == 0 // 2. currentNumber > maxNumber if (value.currentNumber == 0 || value.currentNumber > value.maxNumber) { this.noNeedPaidui = true; this.save(); break; } else { this.noNeedPaidui = false; this.save(); } } logger.debug("merchant id: " + this.merchantId + ", no paidui: " + this.noNeedPaidui); } public boolean checkEditAble(){ boolean flag = false; MorphiaQuery q = Reservation.q(); q.filter("version", this.version); q.filter("valid", true).filter("status", Constants.ReservationStatus.active); if(q.count() == 0){ flag = true; } return flag; } }