示例#1
0
void
CashReconcile::slotShiftClose()
{
    QDate date = _date->getDate();
    Id station_id = stationId();
    Id employee_id = employeeId();

    // Posting time is current time if closing for today or 11:59:59 PM
    QTime time = QTime::currentTime();
    if (date != QDate::currentDate())
	time = QTime(23, 59, 59);

    QString name;
    if (station_id != INVALID_ID) {
	Station station;
	_quasar->db()->lookup(station_id, station);
	name = station.name();
    } else if (employee_id != INVALID_ID) {
	Employee employee;
	_quasar->db()->lookup(employee_id, employee);
	name = employee.nameFL();
    } else {
	name = "<None>";
    }
    if (name.isEmpty()) name = tr("<blank>");

    QString message = "Are you sure you want to ringoff \n\"" + name + "\"";
    int choice = QMessageBox::warning(this, tr("Ringoff?"), message,
				      tr("Yes"), tr("No"));
    if (choice != 0) return;

    // Create the shift
    Shift shift;
    shift.setStoreId(_store->getId());
    shift.setStationId(station_id);
    shift.setEmployeeId(employee_id);
    shift.setPostDate(date);
    shift.setPostTime(time);
    if (!_quasar->db()->create(shift)) {
	message = tr("Failed creating shift close transaction");
	QMessageBox::critical(this, tr("Error"), message);
	return;
    }

    QApplication::setOverrideCursor(waitCursor);
    qApp->processEvents();

    bool result = _quasar->db()->shiftClose(shift);
    QApplication::restoreOverrideCursor();

    if (!result) {
	message = tr("Failed setting shift in transactions");
	QMessageBox::critical(this, tr("Error"), message);
    } else {
	message = "The shift for \"" + name + "\"\nhas been closed";
	QMessageBox::information(this, tr("Information"), message);
	slotRefresh();
    }
}
示例#2
0
void
CashReconcile::slotReconcile()
{
    if (_lines->selectedItem() == NULL) {
	QString message;
	if (_company.shiftMethod() == Company::BY_STATION) {
	    message = tr("A station must be picked");
	} else {
	    message = tr("An employee must be picked");
	}
	QMessageBox::critical(this, tr("Error"), message);
	return;
    }

    Id station_id = stationId();
    Id employee_id = employeeId();
    Id store_id = _store->getId();
    Id safe_store_id = _safeStore->getId();
    Id safe_id = _safeId->getId();
    Id adjust_id = _adjust->getId();
    Id transfer_id = _transfer->getId();

    Id safe_station_id;
    Id safe_employee_id;
    if (_company.shiftMethod() == Company::BY_STATION)
	safe_station_id = safe_id;
    else
	safe_employee_id = safe_id;

    if (store_id == INVALID_ID) {
	QString message = tr("A store must be entered");
	QMessageBox::critical(this, tr("Error"), message);
	_store->setFocus();
	return;
    }
    if (safe_store_id == INVALID_ID) {
	QString message = tr("A safe store must be entered");
	QMessageBox::critical(this, tr("Error"), message);
	_tabs->showPage(_setup);
	_safeStore->setFocus();
	return;
    }
    if (safe_id == INVALID_ID) {
	QString message = tr("A safe must be entered");
	QMessageBox::critical(this, tr("Error"), message);
	_tabs->showPage(_setup);
	_safeId->setFocus();
	return;
    }
    if (adjust_id == INVALID_ID) {
	QString message = tr("An over/short account must be entered");
	QMessageBox::critical(this, tr("Error"), message);
	_tabs->showPage(_setup);
	_adjust->setFocus();
	return;
    }
    if (transfer_id == INVALID_ID) {
	QString message = tr("A transfer account must be entered");
	QMessageBox::critical(this, tr("Error"), message);
	_tabs->showPage(_setup);
	_transfer->setFocus();
	return;
    }
    if (_shifts.size() == 0) {
	QString message = tr("You must have at least one shift");
	QMessageBox::critical(this, tr("Error"), message);
	return;
    }

    QDate date = _date->getDate();
    if (date.isNull()) {
	QString message = tr("The date to reconcile is required");
	QMessageBox::critical(this, tr("Error"), message);
	_date->setFocus();
	return;
    }

    // Posting time is current time if closing for today or 11:59:59 PM
    QTime time = QTime::currentTime();
    if (date != QDate::currentDate())
	time = QTime(23, 59, 59);

    vector<Shift> shifts = _shifts;
    vector<TenderCount> counts = _counts;

    if (shifts.size() > 1 || counts.size() > 1) {
	// TODO: ask which shifts/counts to use
    }

    QApplication::setOverrideCursor(waitCursor);
    qApp->processEvents();

    Id shift_id = shifts[0].id();
    _tenders.clear();
    _summary.clear();

    // Process shifts and add tenders to summary
    unsigned int i;
    for (i = 0; i < shifts.size(); ++i) {
	const Shift& shift = shifts[i];

	GltxSelect conditions;
	conditions.shift_id = shift.id();
	conditions.activeOnly = true;
	vector<Gltx> gltxs;
	_quasar->db()->select(gltxs, conditions);

	for (unsigned int j = 0; j < gltxs.size(); ++j) {
	    const Gltx& gltx = gltxs[j];

	    for (unsigned int k = 0; k < gltx.tenders().size(); ++k) {
		Id tender_id = gltx.tenders()[k].tender_id;
		fixed amount = gltx.tenders()[k].conv_amt;
		if (gltx.tenders()[k].voided) continue;

		addShiftAmt(tender_id, amount);
	    }
	}
    }

    // Process counts and add tenders to summary
    for (i = 0; i < counts.size(); ++i) {
	const TenderCount& count = counts[i];

	for (unsigned int j = 0; j < count.tenders().size(); ++j) {
	    const TenderInfo& info = count.tenders()[j];
	    addCountAmt(info.tender_id, info.amount);
	}
    }

    // Sort tenders by menu number
    std::sort(_summary.begin(), _summary.end());

    // Prepare over/short transaction
    TenderAdjust adjustment;
    adjustment.setPostDate(date);
    adjustment.setPostTime(time);
    adjustment.setMemo(tr("Over/Short"));
    adjustment.setStoreId(store_id);
    adjustment.setStationId(station_id);
    adjustment.setEmployeeId(employee_id);
    adjustment.setShiftId(shift_id);
    adjustment.setAccountId(adjust_id);

    // Prepare transfer out transaction
    TenderAdjust transOut;
    transOut.setPostDate(date);
    transOut.setPostTime(time);
    transOut.setMemo(tr("Deposit to safe"));
    transOut.setStoreId(store_id);
    transOut.setStationId(station_id);
    transOut.setEmployeeId(employee_id);
    transOut.setShiftId(shift_id);
    transOut.setAccountId(transfer_id);

    // Memo for transfer in depends on method
    QString memo;
    if (station_id != INVALID_ID) {
	Station station;
	_quasar->db()->lookup(station_id, station);
	memo = tr("Deposit from: %1").arg(station.name());
    } else {
	Employee employee;
	_quasar->db()->lookup(employee_id, employee);
	memo = tr("Deposit from: %1").arg(employee.nameFL());
    }

    // Prepare transfer in transaction
    TenderAdjust transIn;
    transIn.setPostDate(date);
    transIn.setPostTime(time);
    transIn.setMemo(memo);
    transIn.setStoreId(safe_store_id);
    transIn.setStationId(safe_station_id);
    transIn.setEmployeeId(safe_employee_id);
    transIn.setAccountId(transfer_id);

    // Setup screen
    QDialog* dialog = new QDialog(this, "Summary", true);
    dialog->setCaption(tr("Reconcile Summary"));

    ListView* tenderList = new ListView(dialog);
    tenderList->addTextColumn(tr("Tender"), 20);
    tenderList->addMoneyColumn(tr("Shifts"));
    tenderList->addMoneyColumn(tr("Counts"));
    tenderList->addMoneyColumn(tr("Over/Short"));
    tenderList->setAllColumnsShowFocus(true);
    tenderList->setSorting(-1);

    QFrame* buttons = new QFrame(dialog);
    QPushButton* post = new QPushButton(tr("Reconcile"), buttons);
    QPushButton* cancel = new QPushButton(tr("Cancel"), buttons);
    cancel->setDefault(true);

    connect(post, SIGNAL(clicked()), dialog, SLOT(accept()));
    connect(cancel, SIGNAL(clicked()), dialog, SLOT(reject()));

    QGridLayout* buttonGrid = new QGridLayout(buttons);
    buttonGrid->setSpacing(3);
    buttonGrid->setMargin(3);
    buttonGrid->setColStretch(0, 1);
    buttonGrid->addWidget(post, 0, 1);
    buttonGrid->addWidget(cancel, 0, 2);

    QGridLayout* grid = new QGridLayout(dialog);
    grid->setSpacing(3);
    grid->setMargin(3);
    grid->setRowStretch(0, 1);
    grid->setColStretch(0, 1);
    grid->addWidget(tenderList, 0, 0);
    grid->addWidget(buttons, 1, 0);

    // Process summary info
    fixed shiftsTotal = 0.0;
    fixed countsTotal = 0.0;
    fixed overShort = 0.0;
    fixed transferAmt = 0.0;
    ListViewItem* last = NULL;
    for (i = 0; i < _summary.size(); ++i) {
	const Tender& tender = _summary[i].tender;
	fixed shiftsAmt = _summary[i].shiftsAmt;
	fixed countsAmt = _summary[i].countsAmt;
	fixed overShortAmt = countsAmt - shiftsAmt;

	// Add to table to show to user
	ListViewItem* item = new ListViewItem(tenderList, last);
	last = item;
	item->setValue(0, tender.name());
	item->setValue(1, shiftsAmt);
	item->setValue(2, countsAmt);
	item->setValue(3, overShortAmt);

	// Add to over/short if there is an amount
	if (overShortAmt != 0.0) {
	    TenderLine info;
	    info.tender_id = tender.id();
	    info.conv_amt = overShortAmt;
	    info.conv_rate = tender.convertRate();
	    info.amount = overShortAmt * tender.convertRate();
	    info.amount.moneyRound();
	    info.is_change = false;
	    info.voided = false;
	    adjustment.tenders().push_back(info);
	    overShort += info.amount;
	}

	// Add counted to transfer in/out
	TenderLine info;
	info.tender_id = tender.id();
	info.conv_amt = countsAmt;
	info.conv_rate = tender.convertRate();
	info.amount = countsAmt * tender.convertRate();
	info.amount.moneyRound();
	info.is_change = false;
	info.voided = false;
	transIn.tenders().push_back(info);

	transferAmt += info.amount;
	info.amount = -info.amount;
	info.conv_amt = -info.conv_amt;
	transOut.tenders().push_back(info);

	shiftsTotal += shiftsAmt;
	countsTotal += countsAmt;
    }

    // Add total line
    ListViewItem* item = new ListViewItem(tenderList, last);
    item->setValue(0, tr("Total"));
    item->setValue(1, shiftsTotal);
    item->setValue(2, countsTotal);
    item->setValue(3, countsTotal - shiftsTotal);

    // Show table to user and allow cancel or post
    QApplication::restoreOverrideCursor();
    int ch = dialog->exec();
    if (ch != QDialog::Accepted) return;

    // Check total over/short
    if (overShort > 5.0 || overShort < -5.0) {
	QString message = tr("Warning - your over/short is large.\n"
			     "Are you sure you mean to post this?");
	int ch = QMessageBox::warning(this, tr("Post?"), message,
				      QMessageBox::No, QMessageBox::Yes);
	if (ch != QMessageBox::Yes) return;
    }

    QApplication::setOverrideCursor(waitCursor);
    qApp->processEvents();

    // Add accounts to adjustment
    adjustment.accounts().push_back(AccountLine(adjust_id, -overShort));
    for (i = 0; i < adjustment.tenders().size(); ++i) {
	Id tender_id = adjustment.tenders()[i].tender_id;
	fixed amount = adjustment.tenders()[i].amount;

	Tender tender;
	findTender(tender_id, tender);

	Id tender_acct = tender.accountId();
	if (_company.shiftMethod() == Company::BY_STATION) {
	    if (adjustment.stationId() == safe_station_id)
		if (tender.safeId() != INVALID_ID)
		    tender_acct = tender.safeId();
	} else {
	    if (adjustment.employeeId() == safe_employee_id)
		if (tender.safeId() != INVALID_ID)
		    tender_acct = tender.safeId();
	}

	adjustment.accounts().push_back(AccountLine(tender_acct, amount));
    }

    // Add accounts to transfer out
    transOut.accounts().push_back(AccountLine(transfer_id, transferAmt));
    for (i = 0; i < transOut.tenders().size(); ++i) {
	Id tender_id = transOut.tenders()[i].tender_id;
	fixed amount = transOut.tenders()[i].amount;

	Tender tender;
	findTender(tender_id, tender);

	Id tender_acct = tender.accountId();
	if (_company.shiftMethod() == Company::BY_STATION) {
	    if (transOut.stationId() == safe_station_id)
		if (tender.safeId() != INVALID_ID)
		    tender_acct = tender.safeId();
	} else {
	    if (transOut.employeeId() == safe_employee_id)
		if (tender.safeId() != INVALID_ID)
		    tender_acct = tender.safeId();
	}

	transOut.accounts().push_back(AccountLine(tender_acct, amount));
    }

    // Add accounts to transfer in
    transIn.accounts().push_back(AccountLine(transfer_id, -transferAmt));
    for (i = 0; i < transIn.tenders().size(); ++i) {
	Id tender_id = transIn.tenders()[i].tender_id;
	fixed amount = transIn.tenders()[i].amount;

	Tender tender;
	findTender(tender_id, tender);

	Id tender_acct = tender.safeId();
	if (tender_acct == INVALID_ID)
	    tender_acct = tender.accountId();

	transIn.accounts().push_back(AccountLine(tender_acct, amount));
    }

    // Post adjustment if any tenders
    if (adjustment.tenders().size() > 0) {
	QApplication::restoreOverrideCursor();
	if (!_quasar->db()->create(adjustment)) {
	    QString message = tr("Failed creating over/short transaction");
	    QMessageBox::critical(this, tr("Error"), message);
	    return;
	}
    }

    // Post transfers
    if (!_quasar->db()->create(transOut)) {
	QApplication::restoreOverrideCursor();
	QString message = tr("Failed creating transfer out transaction");
	QMessageBox::critical(this, tr("Error"), message);
	if (adjustment.id() != INVALID_ID)
	    _quasar->db()->remove(adjustment);
	return;
    }
    if (!_quasar->db()->create(transIn)) {
	QApplication::restoreOverrideCursor();
	QString message = tr("Failed creating transfer in transaction");
	QMessageBox::critical(this, tr("Error"), message);
	if (adjustment.id() != INVALID_ID)
	    _quasar->db()->remove(adjustment);
	_quasar->db()->remove(transOut);
	return;
    }

    // Link the transfers
    _quasar->db()->linkTx(transOut.id(), transIn.id());

    // Set shift in shifts
    for (int cnt = shifts.size() - 1; cnt >= 0; --cnt) {
	Shift shift = shifts[cnt];
	shift.setShiftId(shift_id);
	shift.setAdjustmentId(adjustment.id());
	shift.setTransferId(transOut.id());
	_quasar->db()->update(shifts[cnt], shift);
    }

    // Set shift in counts
    for (i = 0; i < counts.size(); ++i) {
	TenderCount count = counts[i];
	count.setShiftId(shift_id);
	_quasar->db()->update(counts[i], count);
    }

    Company orig, company;
    _quasar->db()->lookup(orig);
    company = orig;

    company.setSafeStore(safe_store_id);
    company.setSafeStation(safe_station_id);
    company.setSafeEmployee(safe_employee_id);
    company.setOverShortAccount(adjust_id);
    company.setTransferAccount(transfer_id);
    _quasar->db()->update(orig, company);

    QApplication::restoreOverrideCursor();
    slotRefresh();
}