Winners are rather marked with prize_selected and have it's own endpoint to remove all winners.
		
			
				
	
	
		
			111 lines
		
	
	
		
			3.8 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			111 lines
		
	
	
		
			3.8 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
const path = require("path");
 | 
						|
 | 
						|
const Wine = require(path.join(__dirname, "/schemas/Wine"));
 | 
						|
const PreLotteryWine = require(path.join(__dirname, "/schemas/PreLotteryWine"));
 | 
						|
const VirtualWinner = require(path.join(__dirname, "/schemas/VirtualWinner"));
 | 
						|
 | 
						|
const message = require(path.join(__dirname, "/message"));
 | 
						|
const historyRepository = require(path.join(__dirname, "/history"));
 | 
						|
const winnerRepository = require(path.join(__dirname, "/winner"));
 | 
						|
const wineRepository = require(path.join(__dirname, "/wine"));
 | 
						|
const prelotteryWineRepository = require(path.join(__dirname, "/prelotteryWine"));
 | 
						|
 | 
						|
const { WinnerNotFound, WineSelectionWinnerNotNextInLine, WinnersTimelimitExpired } = require(path.join(
 | 
						|
  __dirname,
 | 
						|
  "/vinlottisErrors"
 | 
						|
));
 | 
						|
 | 
						|
const verifyWinnerNextInLine = async id => {
 | 
						|
  let foundWinner = await VirtualWinner.findOne({ id: id });
 | 
						|
 | 
						|
  if (!foundWinner) {
 | 
						|
    throw new WinnerNotFound();
 | 
						|
  } else if (foundWinner.timestamp_limit < new Date().getTime()) {
 | 
						|
    throw new WinnersTimelimitExpired();
 | 
						|
  }
 | 
						|
 | 
						|
  let allWinners = await VirtualWinner.find().sort({ timestamp_drawn: 1 });
 | 
						|
 | 
						|
  if (
 | 
						|
    foundWinner.timestamp_limit == undefined ||
 | 
						|
    foundWinner.timestamp_sent == undefined ||
 | 
						|
    foundWinner.prize_selected == true
 | 
						|
  ) {
 | 
						|
    throw new WineSelectionWinnerNotNextInLine();
 | 
						|
  }
 | 
						|
 | 
						|
  return Promise.resolve(foundWinner);
 | 
						|
};
 | 
						|
 | 
						|
const claimPrize = (wine, winner) => {
 | 
						|
  return wineRepository
 | 
						|
    .addWine(wine)
 | 
						|
    .then(_ => prelotteryWineRepository.addWinnerToWine(wine, winner)) // prelotteryWine.deleteById
 | 
						|
    .then(_ => historyRepository.addWinnerWithWine(winner, wine)) // wines.js : addWine
 | 
						|
    .then(_ => message.sendWineConfirmation(winner, wine));
 | 
						|
};
 | 
						|
 | 
						|
const notifyNextWinner = async () => {
 | 
						|
  let nextWinner = undefined;
 | 
						|
 | 
						|
  const winnersLeft = await VirtualWinner.find({ prize_selected: false }).sort({ timestamp_drawn: 1 });
 | 
						|
  const winesLeft = await PreLotteryWine.find({ winner: { $exists: false } });
 | 
						|
 | 
						|
  if (winnersLeft.length > 1) {
 | 
						|
    console.log("multiple winners left, choose next in line");
 | 
						|
    nextWinner = winnersLeft[0]; // multiple winners left, choose next in line
 | 
						|
  } else if (winnersLeft.length == 1 && winesLeft.length > 1) {
 | 
						|
    console.log("one winner left, but multiple wines");
 | 
						|
    nextWinner = winnersLeft[0]; // one winner left, but multiple wines
 | 
						|
  } else if (winnersLeft.length == 1 && winesLeft.length == 1) {
 | 
						|
    console.log("one winner and one wine left, choose for user");
 | 
						|
    nextWinner = winnersLeft[0]; // one winner and one wine left, choose for user
 | 
						|
    wine = winesLeft[0];
 | 
						|
    return claimPrize(wine, nextWinner);
 | 
						|
  }
 | 
						|
 | 
						|
  if (nextWinner) {
 | 
						|
    return message.sendPrizeSelectionLink(nextWinner).then(_ => startTimeout(nextWinner.id));
 | 
						|
  } else {
 | 
						|
    console.info("All winners notified. Could start cleanup here.");
 | 
						|
    return Promise.resolve({
 | 
						|
      message: "All winners notified."
 | 
						|
    });
 | 
						|
  }
 | 
						|
};
 | 
						|
 | 
						|
// these need to be register somewhere to cancel if something
 | 
						|
// goes wrong and we want to start prize distribution again
 | 
						|
function startTimeout(id) {
 | 
						|
  const minute = 60000;
 | 
						|
  const minutesForTimeout = 10;
 | 
						|
 | 
						|
  console.log(`Starting timeout for user ${id}.`);
 | 
						|
  console.log(`Timeout duration: ${minutesForTimeout * minute}`);
 | 
						|
  setTimeout(async () => {
 | 
						|
    let virtualWinner = await VirtualWinner.findOne({ id: id, prize_selected: false });
 | 
						|
    if (!virtualWinner) {
 | 
						|
      console.log(`Timeout done for user ${id}, but user has already sent data.`);
 | 
						|
      return;
 | 
						|
    }
 | 
						|
    console.log(`Timeout done for user ${id}, sending update to user.`);
 | 
						|
 | 
						|
    message.sendWineSelectMessageTooLate(virtualWinner);
 | 
						|
 | 
						|
    virtualWinner.timestamp_drawn = new Date().getTime();
 | 
						|
    virtualWinner.timestamp_limit = null;
 | 
						|
    virtualWinner.timestamp_sent = null;
 | 
						|
    await virtualWinner.save();
 | 
						|
 | 
						|
    notifyNextWinner();
 | 
						|
  }, minutesForTimeout * minute);
 | 
						|
 | 
						|
  return Promise.resolve();
 | 
						|
}
 | 
						|
 | 
						|
module.exports = {
 | 
						|
  verifyWinnerNextInLine,
 | 
						|
  claimPrize,
 | 
						|
  notifyNextWinner
 | 
						|
};
 |