⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mschedule.java

📁 Java写的ERP系统
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
/******************************************************************************
 * The contents of this file are subject to the   Compiere License  Version 1.1
 * ("License"); You may not use this file except in compliance with the License
 * You may obtain a copy of the License at http://www.compiere.org/license.html
 * Software distributed under the License is distributed on an  "AS IS"  basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
 * the specific language governing rights and limitations under the License.
 * The Original Code is                  Compiere  ERP & CRM  Business Solution
 * The Initial Developer of the Original Code is Jorg Janke  and ComPiere, Inc.
 * Portions created by Jorg Janke are Copyright (C) 1999-2002 Jorg Janke, parts
 * created by ComPiere are Copyright (C) ComPiere, Inc.;   All Rights Reserved.
 * Contributor(s): ______________________________________.
 *****************************************************************************/
package org.compiere.model;

import java.sql.*;
import java.math.*;
import java.util.*;

import org.compiere.util.*;

/**
 *	Scheduling Utilities.
 *
 * 	@author 	Jorg Janke
 * 	@version 	$Id: MSchedule.java,v 1.8 2003/02/24 04:34:55 jjanke Exp $
 */
public class MSchedule
{
	/**
	 *	Constructor
	 *  @param ctx context
	 */
	public MSchedule (Properties ctx)
	{
		m_ctx = ctx;
	}	//	MSchedule

	private Properties 	m_ctx;
	private int			m_S_Resource_ID;
	private boolean 	m_isAvailable = true;
	private boolean 	m_isSingleAssignment = true;
	private int 		m_S_ResourceType_ID = 0;
	private int 		m_C_UOM_ID = 0;

	private Timestamp	m_startDate = null;
	private Timestamp	m_endDate = null;

	/**	Resource Type Name			*/
	private String		m_typeName = null;
	/**	Resource Type Start Time	*/
	private Timestamp	m_slotStartTime = null;
	/** Resource Type End Time		*/
	private Timestamp	m_slotEndTime = null;

	/**	Time Slots						*/
	private	MAssignmentSlot[] 	m_timeSlots = null;

	/**	Begin Timestamp		1/1/1970			*/
	public static final Timestamp	EARLIEST = new Timestamp(new GregorianCalendar(1970,1,1).getTimeInMillis());
	/**	End Timestamp		12/31/2070			*/
	public static final Timestamp	LATEST = new Timestamp(new GregorianCalendar(2070,12,31).getTimeInMillis());


	/*************************************************************************/

	/**
	 * 	Get Assignments for timeframe.
	 *  <pre>
	 * 		- Resource is Active and Available
	 * 		- Resource UnAvailability
	 * 		- NonBusinessDay
	 * 		- ResourceType Available
	 *  </pre>
	 *  @param S_Resource_ID resource
	 *  @param start_Date start date
	 *  @param end_Date optional end date, need to provide qty to calculate it
	 *  @param qty optional qty in ResourceType UOM - ignored, if end date is not null
	 *  @param getAll if true return all errors
	 *  @return Array of existing Assigments or null - if free
	 */
	public MAssignmentSlot[] getAssignmentSlots (int S_Resource_ID,
		Timestamp start_Date, Timestamp end_Date,
		BigDecimal qty, boolean getAll)
	{
		Log.trace(Log.l4_Data, "MSchedule.getAssignmentSlots", start_Date);
		if (m_S_Resource_ID != S_Resource_ID)
			getBaseInfo (S_Resource_ID);
		//
		ArrayList list = new ArrayList();
		MAssignmentSlot ma = null;

		if (!m_isAvailable)
		{
			ma = new MAssignmentSlot (EARLIEST, LATEST,
				Msg.getMsg (m_ctx, "ResourceNotAvailable"), "", MAssignmentSlot.STATUS_NotAvailable);
			if (!getAll)
				return new MAssignmentSlot[] {ma};
			list.add(ma);
		}

		m_startDate = start_Date;
		m_endDate = end_Date;
		if (m_endDate == null)
			m_endDate = TimeUtil.getEndDate(m_ctx, m_startDate, m_C_UOM_ID, qty);
		Log.trace(Log.l5_DData, "- EndDate=" + m_endDate);


		//	Resource Unavailability -------------------------------------------
	//	Log.trace(Log.l6_Database, "- Unavailability -");
		String sql = "SELECT Description, DateFrom, DateTo "
		  + "FROM S_ResourceUnavailable "
		  + "WHERE S_Resource_ID=?"					//	#1
		  + " AND DateTo >= ?"						//	#2	start
		  + " AND DateFrom <= ?"					//	#3	end
		  + " AND IsActive='Y'";
		try
		{
	//		Log.trace(Log.l6_Database, sql, "ID=" + S_Resource_ID + ", Start=" + m_startDate + ", End=" + m_endDate);
			PreparedStatement pstmt = DB.prepareStatement(sql);
			pstmt.setInt(1, m_S_Resource_ID);
			pstmt.setTimestamp(2, m_startDate);
			pstmt.setTimestamp(3, m_endDate);
			ResultSet rs = pstmt.executeQuery();
			while (rs.next())
			{
				ma = new MAssignmentSlot (TimeUtil.getDay(rs.getTimestamp(2)),
					TimeUtil.getNextDay(rs.getTimestamp(3)),	//	user entered date need to convert to not including end time
					Msg.getMsg (m_ctx, "ResourceUnAvailable"), rs.getString(1),
					MAssignmentSlot.STATUS_UnAvailable);
			//	Log.trace(Log.l6_Database, "- Unavailable", ma);
				if (getAll)
					createDaySlot (list, ma);
				else
					list.add(ma);
			}
			rs.close();
			pstmt.close();
		}
		catch (SQLException e)
		{
			Log.error("MSchedule.getAssignmentSlots-2", e);
			ma = new MAssignmentSlot (EARLIEST, LATEST,
				Msg.getMsg (m_ctx, "ResourceUnAvailable"), e.toString(),
				MAssignmentSlot.STATUS_UnAvailable);
		}
		if (ma != null && !getAll)
			return new MAssignmentSlot[] {ma};


		//	NonBusinessDay ----------------------------------------------------
	//	Log.trace(Log.l6_Database, "- NonBusinessDay -");
		//	"WHERE TRUNC(Date1) BETWEEN TRUNC(?) AND TRUNC(?)"   causes
		//	ORA-00932: inconsistent datatypes: expected NUMBER got TIMESTAMP
		sql = Access.addROAccessSQL (m_ctx,
			"SELECT Name, Date1 FROM C_NonBusinessDay "
			+ "WHERE TRUNC(Date1) BETWEEN ? AND ?",
			"C_NonBusinessDay", false);
		try
		{
			Timestamp startDay = TimeUtil.getDay(m_startDate);
			Timestamp endDay = TimeUtil.getDay(m_endDate);
	//		Log.trace(Log.l6_Database, sql, "Start=" + startDay + ", End=" + endDay);
			PreparedStatement pstmt = DB.prepareStatement(sql);
			pstmt.setTimestamp(1, startDay);
			pstmt.setTimestamp(2, endDay);
			ResultSet rs = pstmt.executeQuery();
			while (rs.next())
			{
				ma = new MAssignmentSlot (TimeUtil.getDay(rs.getTimestamp(2)),
					TimeUtil.getNextDay(rs.getTimestamp(2)),	//	user entered date need to convert to not including end time
					Msg.getMsg(m_ctx, "NonBusinessDay"), rs.getString(1),
					MAssignmentSlot.STATUS_NonBusinessDay);
				Log.trace(Log.l6_Database, "- NonBusinessDay", ma);
				list.add(ma);
			}
			rs.close();
			pstmt.close();
		}
		catch (SQLException e)
		{
			Log.error("MSchedule.getAssignmentSlots-3", e);
			ma = new MAssignmentSlot (EARLIEST, LATEST,
				Msg.getMsg(m_ctx, "NonBusinessDay"), e.toString(),
				MAssignmentSlot.STATUS_NonBusinessDay);
		}
		if (ma != null && !getAll)
			return new MAssignmentSlot[] {ma};


		//	ResourceType Available --------------------------------------------
	//	Log.trace(Log.l6_Database, "- ResourceTypeAvailability -");
		sql = "SELECT Name, IsTimeSlot,TimeSlotStart,TimeSlotEnd, "	//	1..4
			+ "IsDateSlot,OnMonday,OnTuesday,OnWednesday,"			//	5..8
			+ "OnThursday,OnFriday,OnSaturday,OnSunday "			//	9..12
			+ "FROM S_ResourceType "
			+ "WHERE S_ResourceType_ID=?";
		try
		{
			PreparedStatement pstmt = DB.prepareStatement(sql);
			pstmt.setInt(1, m_S_ResourceType_ID);
			ResultSet rs = pstmt.executeQuery();
			if (rs.next())
			{
				m_typeName = rs.getString(1);
				//	TimeSlot
				if ("Y".equals(rs.getString(2)))
				{
					m_slotStartTime = TimeUtil.getDayTime (m_startDate, rs.getTimestamp(3));
					m_slotEndTime = TimeUtil.getDayTime (m_endDate, rs.getTimestamp(4));
					if (TimeUtil.inRange(m_startDate, m_endDate, m_slotStartTime, m_slotEndTime))
					{
						ma = new MAssignmentSlot (m_slotStartTime, m_slotEndTime,
							Msg.getMsg(m_ctx, "ResourceNotInSlotTime"), m_typeName,
							MAssignmentSlot.STATUS_NotInSlotTime);
						if (getAll)
							createTimeSlot (list,
								rs.getTimestamp(3), rs.getTimestamp(4));
					}
				}	//	TimeSlot

				//	DaySlot
				if ("Y".equals(rs.getString(5)))
				{
					if (TimeUtil.inRange(m_startDate, m_endDate,
						"Y".equals(rs.getString(6)), "Y".equals(rs.getString(7)), 				//	Mo..Tu
						"Y".equals(rs.getString(8)), "Y".equals(rs.getString(9)), "Y".equals(rs.getString(10)),	//  We..Fr
						"Y".equals(rs.getString(11)), "Y".equals(rs.getString(12))))
					{
						ma = new MAssignmentSlot (m_startDate, m_endDate,
							Msg.getMsg(m_ctx, "ResourceNotInSlotDay"), m_typeName,
							MAssignmentSlot.STATUS_NotInSlotDay);
						if (getAll)
							createDaySlot (list,
								"Y".equals(rs.getString(6)), "Y".equals(rs.getString(7)), 		//	Mo..Tu
								"Y".equals(rs.getString(8)), "Y".equals(rs.getString(9)), "Y".equals(rs.getString(10)),	//  We..Fr
								"Y".equals(rs.getString(11)), "Y".equals(rs.getString(12)));
					}
				}	//	DaySlot

			}
			rs.close();
			pstmt.close();
		}
		catch (SQLException e)
		{
			Log.error("MSchedule.getAssignmentSlots-4", e);
			ma = new MAssignmentSlot (EARLIEST, LATEST,
				Msg.getMsg(m_ctx, "ResourceNotInSlotDay"), e.toString(),
				MAssignmentSlot.STATUS_NonBusinessDay);
		}
		if (ma != null && !getAll)
			return new MAssignmentSlot[] {ma};

		//	Assignments -------------------------------------------------------
		sql = "SELECT S_ResourceAssignment_ID "
			+ "FROM S_ResourceAssignment "
			+ "WHERE S_Resource_ID=?"					//	#1
			+ " AND AssignDateTo >= ?"					//	#2	start
			+ " AND AssignDateFrom <= ?"				//	#3	end
			+ " AND IsActive='Y'";
		try
		{
			PreparedStatement pstmt = DB.prepareStatement(sql);
			pstmt.setInt(1, m_S_Resource_ID);
			pstmt.setTimestamp(2, m_startDate);
			pstmt.setTimestamp(3, m_endDate);
			ResultSet rs = pstmt.executeQuery();
			while (rs.next())
			{
				MAssignment mAssignment = new MAssignment(Env.getCtx(), rs.getInt(1));
				ma = new MAssignmentSlot (mAssignment);
				if (!getAll)
					break;
				list.add(ma);
			}
			rs.close();
			pstmt.close();
		}
		catch (SQLException e)
		{
			Log.error("MSchedule.getAssignmentSlots-5", e);
			ma = new MAssignmentSlot (EARLIEST, LATEST,
				Msg.translate(m_ctx, "S_R"), e.toString(),
				MAssignmentSlot.STATUS_NotConfirmed);
		}
		if (ma != null && !getAll)
			return new MAssignmentSlot[] {ma};

		/*********************************************************************/

		//	fill m_timeSlots (required for layout)
		createTimeSlots();

		//	Clean list - date range
		ArrayList clean = new ArrayList(list.size());
		for (int i = 0; i < list.size(); i++)
		{
			MAssignmentSlot mas = (MAssignmentSlot)list.get(i);
			if ((mas.getStartTime().equals(m_startDate) || mas.getStartTime().after(m_startDate))
					&& (mas.getEndTime().equals(m_endDate) || mas.getEndTime().before(m_endDate)))
				clean.add(mas);
		}
		//	Delete Unavailability TimeSlots when all day assigments exist
		MAssignmentSlot[] sorted = new MAssignmentSlot[clean.size()];
		clean.toArray(sorted);
		Arrays.sort(sorted, new MAssignmentSlot());	//	sorted by start/end date
		list.clear();	//	used as day list
		clean.clear();	//	cleaned days
		Timestamp sortedDay = null;
		for (int i = 0; i < sorted.length; i++)
		{
			if (sortedDay == null)
				sortedDay = TimeUtil.getDay(sorted[i].getStartTime());
			if (sortedDay.equals(TimeUtil.getDay(sorted[i].getStartTime())))
				list.add(sorted[i]);
			else
			{
				//	process info list -> clean
				layoutSlots (list, clean);
				//	prepare next
				list.clear();
				list.add(sorted[i]);
				sortedDay = TimeUtil.getDay(sorted[i].getStartTime());
			}
		}
		//	process info list -> clean
		layoutSlots (list, clean);

		//	Return
		MAssignmentSlot[] retValue = new MAssignmentSlot[clean.size()];
		clean.toArray(retValue);
		Arrays.sort(retValue, new MAssignmentSlot());	//	sorted by start/end date
		return retValue;
	}	//	getAssignmentSlots

	/**
	 * 	Copy valid Slots of a day from list to clear and layout
	 * 	@param list list with slos of the day
	 * 	@param clean list with only valid slots
	 */
	private void layoutSlots (ArrayList list, ArrayList clean)
	{
		int size = list.size();
	//	System.out.println("Start List=" + size + ", Clean=" + clean.size());
		if (size == 0)
			return;
		else if (size == 1)
		{
			MAssignmentSlot mas = (MAssignmentSlot)list.get(0);
			layoutY (mas);
			clean.add (mas);
			return;
		}

		//	Delete Unavailability TimeSlots when all day assigments exist
		boolean allDay = false;
		for (int i = 0; !allDay && i < size; i++)
		{
			MAssignmentSlot mas = (MAssignmentSlot)list.get(i);
			if (mas.getStatus() == MAssignmentSlot.STATUS_NotAvailable
				|| mas.getStatus() == MAssignmentSlot.STATUS_UnAvailable
				|| mas.getStatus() == MAssignmentSlot.STATUS_NonBusinessDay
				|| mas.getStatus() == MAssignmentSlot.STATUS_NotInSlotDay)
				allDay = true;

		}
		if (allDay)
		{
			//	delete Time Slot
			for (int i = 0; i < list.size(); i++)
			{
				MAssignmentSlot mas = (MAssignmentSlot)list.get(i);
				if (mas.getStatus() == MAssignmentSlot.STATUS_NotInSlotTime)
					list.remove(i--);
			}
		}

		//	Copy & Y layout remaining
		for (int i = 0; i < list.size(); i++)
		{
			MAssignmentSlot mas = (MAssignmentSlot)list.get(i);
			layoutY (mas);
			clean.add (mas);
		}

		//	X layout
		int maxYslots = m_timeSlots.length;
		int[] xSlots = new int[maxYslots];		//	number of parallel slots
		for (int i = 0; i < list.size(); i++)
		{
			MAssignmentSlot mas = (MAssignmentSlot)list.get(i);
			for (int y = mas.getYStart(); y < mas.getYEnd(); y++)
				xSlots[y]++;
		}
		//	Max parallel X Slots
		int maxXslots = 0;
		for (int y = 0; y < xSlots.length; y++)
		{
			if (xSlots[y] > maxXslots)
				maxXslots = xSlots[y];
		}
		//	Only one column
		if (maxXslots < 2)
		{
			for (int i = 0; i < list.size(); i++)
			{
				MAssignmentSlot mas = (MAssignmentSlot)list.get(i);
				mas.setX(0, 1);
			}
			return;
		}

		//	Create xy Matrix
		ArrayList[][] matrix = new ArrayList[maxXslots][maxYslots];
		//	Populate Matrix first column
		for (int y = 0; y < maxYslots; y++)
		{
			ArrayList xyList = new ArrayList();
			matrix[0][y] = xyList;
			//	see if one assignment fits into slot
			for (int i = 0; i < list.size(); i++)
			{
				MAssignmentSlot mas = (MAssignmentSlot)list.get(i);
				if (y >= mas.getYStart() && y <= mas.getYEnd())
					xyList.add(mas);
			}
			//	initiate right columns
			for (int x = 1; x < maxXslots; x++)
				matrix[x][y] = new ArrayList();
		}	//	for all y slots

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -