blob: 0bd139c11facc974e672942958c57d72d4baac55 [file] [log] [blame]
/*******************************************************************************
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*******************************************************************************/
package org.ofbiz.pos.event;
import org.ofbiz.base.util.Debug;
import org.ofbiz.base.util.GeneralException;
import org.ofbiz.base.util.UtilValidate;
import org.ofbiz.pos.PosTransaction;
import org.ofbiz.pos.component.Input;
import org.ofbiz.pos.component.Journal;
import org.ofbiz.pos.screen.PosScreen;
import org.ofbiz.base.util.UtilProperties;
import java.math.BigDecimal;
import java.util.Locale;
public class PaymentEvents {
public static final String module = PaymentEvents.class.getName();
public static synchronized void payCash(PosScreen pos) {
PosTransaction trans = PosTransaction.getCurrentTx(pos.getSession());
trans.clearPayment("CASH");
// all cash transactions are NO_PAYMENT; no need to check
try {
BigDecimal amount = processAmount(trans, pos, null);
Debug.logInfo("Processing [Cash] Amount : " + amount, module);
// add the payment
trans.addPayment("CASH", amount, null, null);
} catch (GeneralException e) {
// errors handled
}
clearInputPaymentFunctions(pos);
pos.refresh();
}
public static synchronized void payCheck(PosScreen pos) {
PosTransaction trans = PosTransaction.getCurrentTx(pos.getSession());
Input input = pos.getInput();
String[] ckInfo = input.getFunction("CHECK");
// check for no/external payment processing
int paymentCheck = trans.checkPaymentMethodType("PERSONAL_CHECK");
if (paymentCheck == PosTransaction.NO_PAYMENT) {
trans.clearPayment("PERSONAL_CHECK");
processNoPayment(pos, "PERSONAL_CHECK");
return;
} else if (paymentCheck == PosTransaction.EXTERNAL_PAYMENT) {
if (ckInfo == null) {
input.setFunction("CHECK");
pos.getOutput().print(UtilProperties.getMessage(PosTransaction.resource,"PosRefNum",Locale.getDefault()));
return;
} else {
processExternalPayment(pos, "PERSONAL_CHECK", ckInfo[1]);
return;
}
}
// now for internal payment processing
pos.showDialog("dialog/error/notyetsupported");
}
public static synchronized void payGiftCard(PosScreen pos) {
PosTransaction trans = PosTransaction.getCurrentTx(pos.getSession());
Input input = pos.getInput();
String[] gcInfo = input.getFunction("GIFTCARD");
// check for no/external payment processing
int paymentCheck = trans.checkPaymentMethodType("GIFT_CARD");
if (paymentCheck == PosTransaction.NO_PAYMENT) {
processNoPayment(pos, "GIFT_CARD");
return;
} else if (paymentCheck == PosTransaction.EXTERNAL_PAYMENT) {
if (gcInfo == null) {
input.setFunction("GIFTCARD");
pos.getOutput().print(UtilProperties.getMessage(PosTransaction.resource,"PosRefNum",Locale.getDefault()));
clearInputPaymentFunctions(pos);
return;
} else {
processExternalPayment(pos, "GIFT_CARD", gcInfo[1]);
return;
}
}
// now for internal payment processing
pos.showDialog("dialog/error/notyetsupported");
clearInputPaymentFunctions(pos);
}
public static synchronized void payCredit(PosScreen pos) {
PosTransaction trans = PosTransaction.getCurrentTx(pos.getSession());
Input input = pos.getInput();
String[] msrInfo = input.getFunction("MSRINFO");
String[] crtInfo = input.getFunction("CREDIT");
String[] track2Info = input.getFunction("TRACK2");
String[] securityCodeInfo = input.getFunction("SECURITYCODE");
String[] postalCodeInfo = input.getFunction("POSTALCODE");
String[] creditExpirationInfo = input.getFunction("CREDITEXP");
// check for no/external payment processing
int paymentCheck = trans.checkPaymentMethodType("CREDIT_CARD");
if (paymentCheck == PosTransaction.NO_PAYMENT) {
processNoPayment(pos, "CREDIT_CARD");
return;
} else if (paymentCheck == PosTransaction.EXTERNAL_PAYMENT) {
if (crtInfo == null) {
input.setFunction("CREDIT");
pos.getOutput().print(UtilProperties.getMessage(PosTransaction.resource,"PosRefNum",Locale.getDefault()));
return;
} else {
processExternalPayment(pos, "CREDIT_CARD", crtInfo[1]);
return;
}
}
// now for internal payment processing
if (crtInfo == null) {
// set total, if entered
input.clearLastFunction();
input.setFunction("TOTAL");
input.setFunction("CREDIT");
pos.getOutput().print(UtilProperties.getMessage(PosTransaction.resource,"PosCredNo",Locale.getDefault()));
} else {
Debug.logInfo("Credit Func Info : " + crtInfo[1], module);
if (msrInfo == null && (creditExpirationInfo == null)) {
//test credit card
if (UtilValidate.isNotEmpty(input.value()) && UtilValidate.isCreditCard(input.value())) {
input.clearLastFunction();
input.setFunction("CREDIT");
input.setFunction("CREDITEXP");
pos.getOutput().print(UtilProperties.getMessage(PosTransaction.resource,"PosCredex",Locale.getDefault()));
} else {
Debug.logInfo("Invalid card number - " + input.value(), module);
clearInputPaymentFunctions(pos);
input.clearInput();
pos.showDialog("dialog/error/invalidcardnumber");
}
} else if (msrInfo == null && (securityCodeInfo == null)) {
// test expiration date
if (UtilValidate.isNotEmpty(input.value()) && (input.value().length() == 4)) {
// ask for Security Code, put in SECURITYCODE
input.clearLastFunction();
input.setFunction("CREDITEXP");
input.setFunction("SECURITYCODE");
pos.getOutput().print(UtilProperties.getMessage(PosTransaction.resource,"PosSecurityCode",Locale.getDefault()));
} else {
Debug.logInfo("Invalid expiration date", module);
clearInputPaymentFunctions(pos);
input.clearInput();
pos.showDialog("dialog/error/invalidexpirationdate");
}
} else if (msrInfo == null && (postalCodeInfo == null)) {
// test security code - allow blank for illegible cards
if (UtilValidate.isEmpty(input.value()) ||
(UtilValidate.isNotEmpty(input.value()) && (input.value().length() <= 4))) {
// ask for Security Code, put in SECURITYCODE
input.clearLastFunction();
input.setFunction("SECURITYCODE");
input.setFunction("POSTALCODE");
pos.getOutput().print(UtilProperties.getMessage(PosTransaction.resource,"PosPostalCode",Locale.getDefault()));
} else {
clearInputPaymentFunctions(pos);
input.clearInput();
pos.showDialog("dialog/error/invalidsecuritycode");
}
} else {
String msrInfoStr = null;
if (msrInfo == null) {
input.clearLastFunction();
input.setFunction("POSTALCODE");
postalCodeInfo = input.getFunction("POSTALCODE");
if (UtilValidate.isNotEmpty(crtInfo[1])) {
if (UtilValidate.isNotEmpty(creditExpirationInfo[1])) {
// setup keyed transaction
msrInfoStr = crtInfo[1] + "|" + creditExpirationInfo[1];
} else {
msrInfoStr = crtInfo[1];
}
}
} else { // is swiped
// grab total from input, if available
input.setFunction("TOTAL");
msrInfoStr = msrInfo[1];
}
input.clearFunction("MSRINFO");
input.setFunction("MSRINFO", msrInfoStr);
String[] msrInfoArr = msrInfoStr.split("\\|");
int allInfo = msrInfoArr.length;
String firstName = null;
String lastName = null;
switch (allInfo) {
case 4:
lastName = msrInfoArr[3];
case 3:
firstName = msrInfoArr[2];
case 2: // card number & exp date found
BigDecimal amount = BigDecimal.ZERO;
try {
String[] totalInfo = input.getFunction("TOTAL");
amount = processAmount(trans, pos, totalInfo[1]);
Debug.logInfo("Processing Credit Card Amount : " + amount, module);
} catch (GeneralException e) {
Debug.logError("Exception caught calling processAmount.", module);
Debug.logError(e.getMessage(), module);
}
String cardNumber = msrInfoArr[0];
String expDate = msrInfoArr[1];
String pmId = trans.makeCreditCardVo(cardNumber, expDate, firstName, lastName);
if (pmId != null) {
trans.addPayment(pmId, amount);
}
if (track2Info != null && UtilValidate.isNotEmpty(track2Info[1])) {
// if swiped
trans.setPaymentTrack2(pmId, null, track2Info[1]);
} else { //keyed
if (securityCodeInfo != null && UtilValidate.isNotEmpty(securityCodeInfo[1])) {
trans.setPaymentSecurityCode(pmId, null, securityCodeInfo[1]);
}
if (postalCodeInfo != null && UtilValidate.isNotEmpty(postalCodeInfo[1])) {
trans.setPaymentPostalCode(pmId, null, postalCodeInfo[1]);
}
}
clearInputPaymentFunctions(pos);
pos.refresh();
break;
case 1: // card number only found
pos.getOutput().print(UtilProperties.getMessage(PosTransaction.resource,"PosCredex",Locale.getDefault()));
break;
default:
Debug.logInfo("Hit the default switch case [" + allInfo + "] refreshing.", module);
input.clearFunction("MSRINFO");
pos.getOutput().print(UtilProperties.getMessage(PosTransaction.resource,"PosCredNo",Locale.getDefault()));
break;
}
}
}
}
private static synchronized void processNoPayment(PosScreen pos, String paymentMethodTypeId) {
PosTransaction trans = PosTransaction.getCurrentTx(pos.getSession());
try {
BigDecimal amount = processAmount(trans, pos, null);
Debug.logInfo("Processing [" + paymentMethodTypeId + "] Amount : " + amount, module);
// add the payment
trans.addPayment(paymentMethodTypeId, amount, null, null);
} catch (GeneralException e) {
// errors handled
}
clearInputPaymentFunctions(pos);
pos.refresh();
}
private static synchronized void processExternalPayment(PosScreen pos, String paymentMethodTypeId, String amountStr) {
PosTransaction trans = PosTransaction.getCurrentTx(pos.getSession());
Input input = pos.getInput();
String refNum = input.value();
if (refNum == null) {
pos.getOutput().print(UtilProperties.getMessage(PosTransaction.resource,"PosRefNum",Locale.getDefault()));
return;
}
input.clearInput();
try {
BigDecimal amount = processAmount(trans, pos, amountStr);
Debug.logInfo("Processing [" + paymentMethodTypeId + "] Amount : " + amount, module);
// add the payment
trans.addPayment(paymentMethodTypeId, amount, refNum, null);
} catch (GeneralException e) {
// errors handled
}
clearInputPaymentFunctions(pos);
pos.refresh();
}
public static synchronized void clearPayment(PosScreen pos) {
PosTransaction trans = PosTransaction.getCurrentTx(pos.getSession());
Journal journal = pos.getJournal();
String sku = journal.getSelectedSku();
String idx = journal.getSelectedIdx();
if (UtilValidate.isNotEmpty(idx) && UtilValidate.isEmpty(sku)) {
int index = -1;
try {
index = Integer.parseInt(idx);
} catch (Exception e) {
}
if (index > -1) {
trans.clearPayment(index);
}
}
clearInputPaymentFunctions(pos);
pos.refresh();
}
public static synchronized void clearAllPayments(PosScreen pos) {
PosTransaction trans = PosTransaction.getCurrentTx(pos.getSession());
trans.clearPayments();
clearInputPaymentFunctions(pos);
pos.refresh();
}
public static synchronized void setRefNum(PosScreen pos) {
PosTransaction trans = PosTransaction.getCurrentTx(pos.getSession());
Journal journal = pos.getJournal();
String sku = journal.getSelectedSku();
String idx = journal.getSelectedIdx();
if (UtilValidate.isNotEmpty(idx) && UtilValidate.isEmpty(sku)) {
String refNum = pos.getInput().value();
if (UtilValidate.isEmpty(refNum)) {
pos.getOutput().print(UtilProperties.getMessage(PosTransaction.resource,"PosRefNum",Locale.getDefault()));
pos.getInput().setFunction("REFNUM");
} else {
int index = -1;
try {
index = Integer.parseInt(idx);
} catch (Exception e) {
}
if (index > -1) {
trans.setPaymentRefNum(index, refNum, refNum);
pos.refresh();
}
}
} else {
pos.refresh();
}
clearInputPaymentFunctions(pos);
}
public static synchronized void processSale(PosScreen pos) {
PosTransaction trans = PosTransaction.getCurrentTx(pos.getSession());
Locale defaultLocale = Locale.getDefault();
if (trans.isEmpty()) {
PosScreen newPos = pos.showPage("pospanel");
newPos.showDialog("dialog/error/noitems");
} else if (trans.getTotalDue().compareTo(BigDecimal.ZERO) > 0) {
pos.showDialog("dialog/error/exception", UtilProperties.getMessage("XuiLabels", "NOT_ENOUGH_FUNDS", defaultLocale));
trans.clearPayment("CASH");
} else {
// manual locks (not secured; will be unlocked on clear)
pos.setWaitCursor();
PosScreen.currentScreen.getOutput().print(UtilProperties.getMessage(PosTransaction.resource, "PosProcessing", defaultLocale));
pos.getInput().setLock(true);
pos.getButtons().setLock(true);
pos.refresh(false);
// process the sale
try {
trans.processSale(pos.getOutput());
pos.getInput().setFunction("PAID");
} catch (GeneralException e) {
Debug.logError(e, e.getMessage(), module);
pos.getInput().setLock(false);
pos.getButtons().setLock(false);
pos.showDialog("dialog/error/exception", e.getMessage());
}
clearInputPaymentFunctions(pos);
pos.setNormalCursor();
}
}
private static synchronized BigDecimal processAmount(PosTransaction trans, PosScreen pos, String amountStr) throws GeneralException {
Input input = pos.getInput();
if (input.isFunctionSet("TOTAL")) {
String amtStr = amountStr != null ? amountStr : input.value();
BigDecimal amount;
if (UtilValidate.isNotEmpty(amtStr)) {
try {
amount = new BigDecimal(amtStr);
} catch (NumberFormatException e) {
Debug.logError("Invalid number for amount : " + amtStr, module);
pos.getOutput().print("Invalid Amount!");
input.clearInput();
throw new GeneralException();
}
amount = amount.movePointLeft(2); // convert to decimal
Debug.logInfo("Set amount / 100 : " + amount, module);
} else {
Debug.logInfo("Amount is empty; assumption is full amount : " + trans.getTotalDue(), module);
amount = trans.getTotalDue();
if (amount.compareTo(BigDecimal.ZERO) <= 0) {
throw new GeneralException();
}
}
return amount;
} else {
Debug.logInfo("TOTAL function NOT set", module);
throw new GeneralException();
}
}
// Removes all payment functions from the input function stack
// Useful for clearing redundant data after a payment has been
// processed or if an error occurred
public static synchronized void clearInputPaymentFunctions(PosScreen pos) {
String[] paymentFuncs = {"CHECK", "CHECKINFO", "CREDIT",
"GIFTCARD", "MSRINFO", "REFNUM", "CREDITEXP",
"TRACK2", "SECURITYCODE", "POSTALCODE" };
Input input = pos.getInput();
for (int i = 0; i < paymentFuncs.length; i++) {
while (input.isFunctionSet(paymentFuncs[i])) {
input.clearFunction(paymentFuncs[i]);
}
}
}
}