/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package clips.shedule.reception;
import TimeTable.Day;
import TimeTable.DayOfWeek;
import TimeTable.JTimeTable;
import TimeTable.model.TimeTableModelDefault;
import TimeTable.spans.TimeSpan;
import cli_fmw.delegate.AuditListener;
import clips.delegate.client.ClientLocal;
import clips.delegate.directory.complex.DirectoryCabinetItem;
import clips.delegate.service.SerRenLocal;
import clips.delegate.shedule.individual.SheduleIndividualData;
import clips.delegate.shedule.individual.SheduleIndividualLocal;
import clips.delegate.shedule.individual.WeekIndex;
import cli_fmw.main.ClipsException;
import clips.delegate.shedule.reception.SheduleReceptionData;
import cli_fmw.main.ContentStateListener;
import cli_fmw.main.MainWindow;
import cli_fmw.main.PrintCreators;
import cli_fmw.main.audit.AuditManager;
import cli_fmw.report.TableReportOptions;
import clips.userseach.PanelUserSearch;
import cli_fmw.utils.EmptyDialog;
import cli_fmw.utils.MessageBox;
import cli_fmw.utils.ModalDialog;
import cli_fmw.utils.SelectorEditable;
import clips.delegate.directory.ro.DirectoryCollaboratorItem;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
import javax.swing.text.JTextComponent;
import framework.utils.Converter;
/**
*
* @author Axe Ilshat
*/
public class SheduleReceptionTableModel extends TimeTableModelDefault {
private SelectorEditable<SheduleReceptionData> recs;
private ClientLocal defaultClient;
private Day day;
private DirectoryCollaboratorItem collaborator;
private JTextComponent descriptor;
private Map<Integer, List<SerRenLocal>> serviceRenders = //client => services
new HashMap<Integer, List<SerRenLocal>>();
private AuditManager am;
private static ContentStateListener emptyListener = new ContentStateListener() {
@Override
public void contentStateChanged() {
}
};
/**
* Creates a new instance of SheduleWeekTableModel
* @param swl - week delegate
* @throws java.lang.Exception
*/
public SheduleReceptionTableModel(SelectorEditable<SheduleReceptionData> recs,
ClientLocal client, Day day, DirectoryCollaboratorItem collaborator, JTextComponent descriptor, AuditManager am)
throws ClipsException {
this.defaultClient = client;
this.am = am;
this.day = day;
this.recs = recs;
this.collaborator = collaborator;
this.descriptor = descriptor;
for(int i=0; i<recs.size(); i++) {
SheduleReceptionData item = recs.get(i);
TimeSpanItem span = new TimeSpanItem(item);
addTimeSpan(span);
}
if(client != null) {
serviceRenders.put(client.getID(), client.getSerRenListToRender());
}
System.out.println(getClass().getName() + " constructor: " + getSpanCount() + " loaded");
}
private List<SerRenLocal> getServices(ClientLocal client) throws ClipsException {
List<SerRenLocal> res = serviceRenders.get(client.getID());
if(res == null) {
res = client.getSerRenListToRender();
serviceRenders.put(client.getID(), res);
}
return res;
}
/**
* Подтверждает у пользователя и удалеет спан, информирует таблицы
* @param span
*/
private void removeSpanWithConformation(TimeSpanItem span) {
if (MessageBox.showConfirmYesNo(MessageBox.C_DEL_RECORD_ON_RECEPTION) == MessageBox.ANSWER_YES) {
TimeSpanItem itemSpan = span;
SheduleReceptionData work = itemSpan.get();
recs.remove(work);
removeTimeSpan(span);
//обновляем информацию в кеше о том, что некоторые услуги перестали быть записанными на прием
try {
ClientLocal client = work.getClient(am);
List<SerRenLocal> clientServices = getServices(client);
//update available function
List<Integer> orphanServices = work.getLinkedServicesList();
for (int i = 0; i < clientServices.size(); i++) {
SerRenLocal s = clientServices.get(i);
s.addContentStateListener(emptyListener);
if (orphanServices.contains(s.getID())) {
s.setReception(null);
}
}
} catch (ClipsException ex) {
ex.printStackTrace();
}
}
}
/**
* Вызывается контролом при изменении размеров спана
* @param span
* @param table
*/
@Override
public void spanResized(TimeSpan span, JTimeTable table) {
TimeSpanItem itemSpan = (TimeSpanItem) span;
SheduleReceptionData item = itemSpan.get();
item.setBegin(span.getBegin());
item.setDuration(span.getLength());
}
/**
* Вызывается контролом при перемещении спана
* @param span
* @param table
*/
@Override
public void spanMoved(TimeSpan span, JTimeTable table) {
TimeSpanItem itemSpan = (TimeSpanItem) span;
SheduleReceptionData item = itemSpan.get();
item.setBegin(span.getBegin());
item.setDuration(span.getLength());
}
@Override
public void mouseOverSpan(TimeSpan span, JTimeTable table) {
}
@Override
public void mouseLeftSpan(TimeSpan span, JTimeTable table) {
if(descriptor != null) {
descriptor.setText("");
}
}
@Override
public void mouseEnterSpan(TimeSpan span, JTimeTable table) {
if(span instanceof TimeSpanItem) {
TimeSpanItem tsi = (TimeSpanItem) span;
String desc = tsi.get().getDescription();
if(desc != null && !desc.isEmpty()) {
desc += "\nУслуги:\n";
} else {
desc = "Услуги:\n";
}
//получаем список услуг необслуженных услуг клиента и отображаем их
try {
SheduleReceptionData data = tsi.get();
List<Integer> srl = data.getLinkedServicesList();
List<SerRenLocal> clientServices = getServices(data.getClient(am));
for (int i = 0; i < clientServices.size(); i++) {
SerRenLocal s = clientServices.get(i);
if (srl.contains(s.getID())) {
try {
desc += " - " + s.getService().getTitle() + "\n";
} catch (ClipsException ex) {
ex.printStackTrace();
}
}
}
} catch (ClipsException ex) {
ex.printStackTrace();
}
descriptor.setText(desc);
}
}
/**
* Функция вызывается при двойном щелчке на спане
* @param span
* @param table
*/
@Override
public void spanActivated(TimeSpan span, JTimeTable table) {
showSpanDetails((TimeSpanItem) span);
}
/**
* Функция вызывается при нажатии клавиши контестного меню на активном span'e
* @param span
* @param table
* @param x - позиция курсора мыши
* @param y - позиция курсора мыши
*/
@Override
public void spanContextMenu(TimeSpan span, JTimeTable table, int x, int y) {
TimeSpanItem itemSpan = (TimeSpanItem) span;
JPopupMenu popup = new JPopupMenu();
//details
JMenuItem menuItem = new JMenuItem("Подробнее о приеме...");
menuItem.addActionListener(new SpanAction(itemSpan, SpanAction.DETAILS));
popup.add(menuItem);
//delete
menuItem = new JMenuItem("Удалить запись на прием");
menuItem.addActionListener(new SpanAction(itemSpan, SpanAction.DELETE));
popup.add(menuItem);
//print
menuItem = new JMenuItem("Печать данных записи на прием");
menuItem.addActionListener(new SpanAction(itemSpan, SpanAction.PRINT));
popup.add(menuItem);
popup.show(table, x, y);
}
/**
* Функция вызывается при нажатии клавиши контестного меню
* @param table - таблица
* @param x - позиция курсора мыши
* @param y - позиция курсора мыши
*/
@Override
public void contextMenu(JTimeTable table, int x, int y) {
JPopupMenu popup = new JPopupMenu();
JMenuItem menuItem = new JMenuItem("Записать на прием...");
menuItem.addActionListener(new AddNewSpanAction(table.getTimeAt(y)));
popup.add(menuItem);
popup.show(table, x, y);
}
/**
* Показывает диалог подробной информации о спане
* @param dayOfWeek
* @param span
*/
private void showSpanDetails(TimeSpanItem span) {
try {
SheduleReceptionData item = span.get();
ClientLocal client = item.getClient(am);
List<SerRenLocal> clientServices = getServices(client);
SheduleItemDialog dlg = new SheduleItemDialog(MainWindow.mainWindow, clientServices.iterator(), getAuditManager());
Calendar gc = GregorianCalendar.getInstance();
gc.setTime(item.getBegin());
dlg.hBegin.setValue(gc.get(Calendar.HOUR_OF_DAY));
dlg.mBegin.setValue(gc.get(Calendar.MINUTE));
dlg.hDuration.setValue(item.getDuration() / 60);
dlg.mDuration.setValue(item.getDuration() % 60);
dlg.description.setText(item.getDescription());
dlg.setServiceSelectedList(item.getLinkedServicesList());
dlg.setVisible(true);
if (dlg.getDlgResult() == ModalDialog.DLG_OK) {
SheduleReceptionData saved = (SheduleReceptionData) item.clone();
try {
update(item, dlg, gc);
span.itemChanged();
} catch (ClipsException ex) {
item.setBegin(saved.getBegin());
item.setDuration(saved.getDuration());
item.setDescription(saved.getDescription());
MessageBox.showException(ex);
}
} else if (dlg.getDlgResult() == SheduleItemDialog.DLG_DELETED) {
removeSpanWithConformation(span);
}
}
catch (ClipsException ex) {
MessageBox.showException(ex);
}
}
/**
* печатает спан
* @param span
*/
private void printSpanDetails(TimeSpanItem span) {
try {
SheduleReceptionData item = span.get();
HashMap<String, Object> data = new LinkedHashMap<String, Object>();
String title = "Запись на прием:";
data.put("clientFIO", "Пациент: " + item.getClient(am).toString());
data.put("collabFIO", "Врач: " + item.getCollaborator().getTitle());
data.put("date", "Дата: " + Converter.dateToString(item.getBegin()));
DayOfWeek dayOfWeek = day.getDayOfWeek();
SheduleIndividualLocal sil = new SheduleIndividualLocal(collaborator);
WeekIndex weekIndex = new WeekIndex(day);
Iterator<SheduleIndividualData> it = sil.daySelector(weekIndex, dayOfWeek);
if (!it.hasNext()) {
WeekIndex planWeekIndex = new WeekIndex(weekIndex.getIndex() % sil.getWeekCount());
it = sil.daySelector(planWeekIndex, dayOfWeek);
}
DirectoryCabinetItem cabinet = null;
Calendar itemBegin = new GregorianCalendar();
itemBegin.setTime(item.getBegin());
Calendar itemEnd = new GregorianCalendar();
itemEnd.setTime(item.getEnd());
Calendar workBegin = new GregorianCalendar();
Calendar workEnd = new GregorianCalendar();
int year = itemBegin.get(Calendar.YEAR);
int month = itemBegin.get(Calendar.MONTH);
int dayy = itemBegin.get(Calendar.DAY_OF_MONTH);
while (it.hasNext()) {
SheduleIndividualData work = it.next();
workBegin.setTime(work.getBegin());
workBegin.set(year, month, dayy);
workEnd.setTime(work.getBegin());
workEnd.add(Calendar.MINUTE, work.getWorkDuration());
workEnd.set(year, month, dayy);
if ((itemBegin.after(workBegin) || itemBegin.equals(workBegin)) &&
(itemEnd.before(workEnd) || itemEnd.equals(workEnd))) {
cabinet = work.getCabinet();
break;
}
}
Calendar tb = GregorianCalendar.getInstance();
Calendar te = GregorianCalendar.getInstance();
tb.setTime(item.getBegin());
te.setTime(item.getEnd());
String period = String.format("%02d:%02d-%02d:%02d", tb.get(Calendar.HOUR_OF_DAY),
tb.get(Calendar.MINUTE), te.get(Calendar.HOUR_OF_DAY), te.get(Calendar.MINUTE));
data.put("period", "Время: " + period);
String services = "";
List<Integer> srl = item.getLinkedServicesList();
List<SerRenLocal> clientServices = getServices(item.getClient(am));
if (srl.size() != 0) {
for (int i = 0; i < clientServices.size(); i++) {
SerRenLocal s = clientServices.get(i);
if (srl.contains(s.getID())) {
services += " - " + s.getService().getTitle() + "\n";
}
}
}
else {
services += " нет привязанных услуг";
}
data.put("services", "Привязанные услуги: \n" + services);
if (!item.getDescription().isEmpty()) {
data.put("description", "Примечание: \n" + item.getDescription());
}
if (cabinet != null) {
String cab = cabinet.getTitle();
cab += " (" + cabinet.getDescription() + ")";
data.put("cabinet", "Кабинет: " + cab);
}
TableReportOptions ops = new TableReportOptions();
ops.setPageA5();
PrintCreators.createGeneratedReport(title, ops, data.entrySet(), null, null, getClass());
} catch (ClipsException ex) {
MessageBox.showException(ex);
}
}
private void update(SheduleReceptionData data, SheduleItemDialog dlg, Calendar dayTime) throws ClipsException {
dayTime.set(GregorianCalendar.HOUR_OF_DAY, (Integer) dlg.hBegin.getValue());
dayTime.set(GregorianCalendar.MINUTE, (Integer) dlg.mBegin.getValue());
data.setBegin(dayTime.getTime());
data.setDuration((Integer) dlg.hDuration.getValue() * 60 + (Integer) dlg.mDuration.getValue());
data.setDescription(dlg.description.getText());
//fresh linked services list
List<SerRenLocal> srl = dlg.getServiceSelectedList();
List<Integer> li = new ArrayList<Integer>();
if(srl != null) {
for(int i=0; i<srl.size(); i++) {
li.add(new Integer(srl.get(i).getID()));
}
}
data.setLinkedServicesList(li);
ClientLocal client = data.getClient(am);
List<SerRenLocal> clientServices = getServices(client);
//update available function
//нахрен это???
/*for(int i=0; i<clientServices.size(); i++) {
SerRenLocal s = clientServices.get(i);
s.addContentStateListener(emptyListener);
if(srl.contains(s)) {
s.setReception(data);
}
}*/
}
public AuditManager getAuditManager() {
return am;
}
/**
* Context menu action
*/
protected class AddNewSpanAction implements ActionListener {
int minutes;
public AddNewSpanAction(int milliseconds) {
this.minutes = milliseconds/60000;
}
@Override
public void actionPerformed(ActionEvent e) {
try {
ClientLocal client = null;
if(defaultClient != null) {
client = defaultClient;
} else {
EmptyDialog dialog = new EmptyDialog(null, "Выбор пациента", getAuditManager());
PanelUserSearch panel = new PanelUserSearch(dialog, PanelUserSearch.MODE_SELECT);
dialog.addNewPage(panel, null);
dialog.setVisible(true);
if (dialog.getDlgResult() == ModalDialog.DLG_OK) {
client = panel.getSelectedClient();
} else {
return;
}
}
List<SerRenLocal> clientServices = getServices(client);
SheduleItemDialog dlg = new SheduleItemDialog(MainWindow.mainWindow, clientServices.iterator(), getAuditManager());
dlg.delBtn.setEnabled(false);
dlg.hBegin.setValue(minutes/60);
dlg.mBegin.setValue(minutes%60);
dlg.mDuration.setValue(10);
dlg.setVisible(true);
if (dlg.getDlgResult() == ModalDialog.DLG_OK) {
Calendar gc = day.getCalendar();
SheduleReceptionData item = new SheduleReceptionData(client, collaborator);
update(item, dlg, gc);
recs.append(item);
addTimeSpan(new TimeSpanItem(item));
fireTimeModelEvent();
}
} catch (ClipsException ex) {
MessageBox.showException(ex);
}
}
}
/**
* Context menu action
*/
protected class SpanAction implements ActionListener {
public static final int DETAILS = 0;
public static final int DELETE = 1;
public static final int ADDNEW = 2;
public static final int PRINT = 3;
TimeSpanItem itemSpan;
int action;
SpanAction(TimeSpanItem itemSpan, int action) {
this.itemSpan = itemSpan;
this.action = action;
}
@Override
public void actionPerformed(ActionEvent e) {
switch (action) {
case DETAILS:
showSpanDetails(itemSpan);
break;
case DELETE:
removeSpanWithConformation(itemSpan);
break;
case PRINT:
printSpanDetails(itemSpan);
break;
}
}
}
}