/**
* Copyright (c) 2015 Mustafa DUMLUPINAR, mdumlupinar@gmail.com
*
* This file is part of seyhan project.
*
* seyhan is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package utils;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.OptimisticLockException;
import models.AbstractBaseTrans;
import models.AbstractDocTrans;
import models.AbstractStockTrans;
import models.Bank;
import models.BankExpense;
import models.BankTrans;
import models.BankTransSource;
import models.ChqbllPayroll;
import models.Contact;
import models.ContactTrans;
import models.ContactTransSource;
import models.InvoiceTrans;
import models.OrderTrans;
import models.Safe;
import models.SafeTrans;
import models.SafeTransSource;
import models.WaybillTrans;
import models.temporal.Pair;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import play.i18n.Messages;
import com.avaje.ebean.Ebean;
import controllers.global.Profiles;
import enums.DocNoIncType;
import enums.Module;
import enums.Right;
import enums.TransType;
/**
* @author mdpinar
*/
public class RefModuleUtil {
private final static Logger log = LoggerFactory.getLogger(RefModuleUtil.class);
private static List<Module> BASE_MODULE_LIST;
static {
BASE_MODULE_LIST = new ArrayList<Module>();
BASE_MODULE_LIST.add(Module.contact);
BASE_MODULE_LIST.add(Module.safe);
BASE_MODULE_LIST.add(Module.bank);
}
public static String save(AbstractBaseTrans source, Module module) {
return save(source, module, null, false);
}
public static String save(AbstractBaseTrans source, Module module, Contact extraContact) {
return save(source, module, extraContact, false);
}
public static String save(AbstractBaseTrans source, Module module, Contact extraContact, boolean isTransactionNeeded) {
ContactTrans oldContactTrans = null;
SafeTrans oldSafeTrans = null;
BankTrans oldBankTrans = null;
AbstractDocTrans newTrans = null;
Module orphanModule = null;
if (source.refId != null && source.refOldModule != null) {
switch (source.refOldModule) {
case contact: {
oldContactTrans = ContactTrans.findById(source.refId);
orphanModule = Module.contact;
break;
}
case safe: {
oldSafeTrans = SafeTrans.findById(source.refId);
orphanModule = Module.safe;
break;
}
case bank: {
oldBankTrans = BankTrans.findById(source.refId);
orphanModule = Module.bank;
break;
}
default: {
oldContactTrans = ContactTrans.findById(source.refId);
orphanModule = Module.contact;
break;
}
}
}
if (isTransactionNeeded) Ebean.beginTransaction();
try {
if (source.refModule != null) {
switch (source.refModule) {
case no: {
source.refId = null;
source.refModule = null;
break;
}
case contact: {
newTrans = (oldContactTrans != null ? oldContactTrans : new ContactTrans((module.equals(source.refModule) ? Right.CARI_VIRMAN : source.right)));
((ContactTrans)newTrans).contact = source.refContact;
((ContactTrans)newTrans).transSource = source.refContactTransSource;
break;
}
case safe: {
newTrans = (oldSafeTrans != null ? oldSafeTrans : new SafeTrans((module.equals(source.refModule) ? Right.KASA_VIRMAN : source.right)));
((SafeTrans)newTrans).safe = source.refSafe;
((SafeTrans)newTrans).transSource = source.refSafeTransSource;
break;
}
case bank: {
newTrans = (oldBankTrans != null ? oldBankTrans : new BankTrans((module.equals(source.refModule) ? Right.BANK_VIRMAN : source.right)));
((BankTrans)newTrans).bank = source.refBank;
((BankTrans)newTrans).transSource = source.refBankTransSource;
((BankTrans)newTrans).expense = source.bankExpense;
((BankTrans)newTrans).expenseAmount = source.bankExpenseAmount;
break;
}
}
if (newTrans != null) {
newTrans.bankExpense = source.bankExpense;
newTrans.bankExpenseAmount = source.bankExpenseAmount;
}
}
if (source instanceof AbstractDocTrans) {
((AbstractDocTrans)source).transDir = (((AbstractDocTrans)source).debt.doubleValue() > 0 ? 0 : 1);
}
source.transYear = DateUtils.getYear(source.transDate);
source.transMonth = DateUtils.getYearMonth(source.transDate);
if (source.id == null) {
if ((source.transNo == null || source.transNo.isEmpty())
&& Profiles.chosen().gnel_docNoIncType.equals(DocNoIncType.Full_Automatic)) source.transNo = DocNoUtils.findLastTransNo(source.right);
source.receiptNo = DocNoUtils.findLastReceiptNo(source.right);
}
double amount = 0d;
double debt = 0d;
double credit = 0d;
if (source instanceof AbstractStockTrans) {
AbstractStockTrans ast = (AbstractStockTrans) source;
amount = ast.netTotal;
} else if (source instanceof ChqbllPayroll) {
ChqbllPayroll ast = (ChqbllPayroll) source;
amount = ast.total;
} else {
AbstractDocTrans ast = (AbstractDocTrans) source;
amount = ast.amount;
}
if (source.transType.equals(TransType.Debt) || source.transType.equals(TransType.Input)) {
debt = amount;
} else {
credit = amount;
}
if (newTrans != null) {
newTrans.workspace = source.workspace;
newTrans.receiptNo = source.receiptNo;
newTrans.refModule = module;
newTrans.transType = (source.transType.equals(TransType.Debt) || source.transType.equals(TransType.Input) ? TransType.Credit : TransType.Debt);
if (Profiles.chosen().gnel_hasExchangeSupport) {
newTrans.amount = source.refExcEquivalent;
if (newTrans.transType.equals(TransType.Debt)) {
newTrans.debt = newTrans.amount;
newTrans.credit = 0d;
} else {
newTrans.debt = 0d;
newTrans.credit = newTrans.amount;
}
newTrans.excCode = source.refExcCode;
newTrans.excRate = source.refExcRate;
newTrans.excEquivalent = source.excEquivalent;
} else {
newTrans.amount = amount;
newTrans.credit = debt;
newTrans.debt = credit;
}
newTrans.transDate = source.transDate;
newTrans.transNo = source.transNo;
newTrans.transDir = (newTrans.debt.doubleValue() > 0 ? 0 : 1);
newTrans.transYear = source.transYear;
newTrans.transMonth = source.transMonth;
newTrans.description = source.description;
log.info("newTrans.expense : " + newTrans.bankExpense + " -> newTrans.expenseAmount : " + newTrans.bankExpenseAmount);
log.info("source.expense : " + source.bankExpense + " -> source.expenseAmount : " + source.bankExpenseAmount);
if (newTrans.id == null) {
if (Profiles.chosen().gnel_docNoIncType.equals(DocNoIncType.Full_Automatic)) newTrans.transNo = DocNoUtils.findLastTransNo(newTrans.right);
newTrans.singleSave();
} else {
newTrans.singleUpdate();
}
source.refId = newTrans.id;
}
if (source.id == null) {
source.save();
} else {
source.update();
}
if (newTrans != null) {
newTrans.refId = source.id;
newTrans.refModule = source.right.module;
newTrans.singleUpdate();
}
if (orphanModule != null && (source.refModule == null || ! source.refModule.equals(orphanModule))) {
if (oldContactTrans != null) oldContactTrans.singleDelete();
if (oldSafeTrans != null) oldSafeTrans.singleDelete();
if (oldBankTrans != null) oldBankTrans.singleDelete();
}
/*
* Kasa, Banka ve Cari disindaki moduller ekstra Cari Hareket yansimasi yapabilirler
*
* @see StockTrans
*/
if (! BASE_MODULE_LIST.contains(source.right.module)) {
ContactTrans extraTrans = ContactTrans.findByRefIdAndRight(source.id, source.right);
boolean hasContact = (extraContact != null && extraContact.id != null);
//Eski yansima var ve yeni yansima olmayacaksa eski yanisma silinir!
if (extraTrans != null && ! hasContact) {
extraTrans.singleDelete();
// Yansima olacaksa; eski yanisma varsa update edilir, yoksa yeni bir tane olusturulur!
} else if (hasContact) {
if (extraTrans == null) extraTrans = new ContactTrans(source.right);
extraTrans.workspace = source.workspace;
extraTrans.contact = extraContact;
extraTrans.receiptNo = source.receiptNo;
extraTrans.transType = (source.transType.equals(TransType.Debt) || source.transType.equals(TransType.Input) ? TransType.Credit : TransType.Debt);
extraTrans.amount = amount;
extraTrans.debt = credit;
extraTrans.credit = debt;
extraTrans.excCode = source.excCode;
extraTrans.excRate = source.excRate;
extraTrans.excEquivalent = source.excEquivalent;
extraTrans.transDate = source.transDate;
extraTrans.transNo = source.transNo;
extraTrans.transDir = (extraTrans.debt.doubleValue() > 0 ? 0 : 1);
extraTrans.transYear = source.transYear;
extraTrans.transMonth = source.transMonth;
extraTrans.description = source.description;
extraTrans.refId = source.id;
extraTrans.refModule = source.right.module;
if (extraTrans.id == null) {
extraTrans.singleSave();
} else {
extraTrans.singleUpdate();
}
}
/*
* Fatura islemi ve pesin ise hesap kapama islemi icin bir hareket kaydi daha olusturulur
*/
if (source instanceof InvoiceTrans && extraTrans != null) {
InvoiceTrans asAnInvoiceTrans = (InvoiceTrans) source;
ContactTrans closingTrans = ContactTrans.findByRefIdAndRight(source.id, Right.CARI_ISLEM_KAPAMA);
//Eski kapama var ve fatura pesin degilse eski kapama islemi silinir!
if (closingTrans != null && ! asAnInvoiceTrans.isCash) {
closingTrans.singleDelete();
// Kapama olacaksa; eski kapama islemi varsa update edilir, yoksa yeni bir tane olusturulur!
} else if (asAnInvoiceTrans.isCash) {
if (closingTrans == null) closingTrans = new ContactTrans(Right.CARI_ISLEM_KAPAMA);
closingTrans.workspace = extraTrans.workspace;
closingTrans.contact = extraTrans.contact;
closingTrans.receiptNo = extraTrans.receiptNo;
closingTrans.transType = (extraTrans.transType.equals(TransType.Debt) ? TransType.Credit : TransType.Debt);
closingTrans.amount = extraTrans.amount;
closingTrans.debt = extraTrans.credit;
closingTrans.credit = extraTrans.debt;
closingTrans.excCode = extraTrans.excCode;
closingTrans.excRate = extraTrans.excRate;
closingTrans.excEquivalent = extraTrans.excEquivalent;
closingTrans.transDate = extraTrans.transDate;
closingTrans.transNo = extraTrans.transNo;
closingTrans.transDir = (extraTrans.debt.doubleValue() > 0 ? 1 : 0);
closingTrans.transYear = source.transYear;
closingTrans.transMonth = source.transMonth;
closingTrans.description = "PEŞİN FATURA İŞLEM KAPAMA (FATURA NO : " + asAnInvoiceTrans.transNo +")";
closingTrans.refId = source.id;
closingTrans.refModule = Module.invoice;
if (closingTrans.id == null) {
closingTrans.singleSave();
} else {
closingTrans.singleUpdate();
}
}
}
}
/*
* Masraf bilgisi varsa ekstra bir hareket yansimasi daha yapilir
*/
BankTrans expenseTrans = BankTrans.findByRefIdAndRight(source.id, Right.BANK_MASRAF);
boolean hasExpense = (source.refModule != null && source.refModule.equals(Module.bank) && newTrans.bankExpenseAmount != null && newTrans.bankExpenseAmount.doubleValue() > 0);
//Eski yansima var ve yeni yansima olmayacaksa eski yanisma silinir!
if (expenseTrans != null && ! hasExpense) {
expenseTrans.singleDelete();
// Yansima olacaksa; eski yanisma varsa update edilir, yoksa yeni bir tane olusturulur!
} else if (hasExpense) {
if (expenseTrans == null) expenseTrans = new BankTrans(Right.BANK_MASRAF);
expenseTrans.workspace = source.workspace;
expenseTrans.bank = source.refBank;
expenseTrans.receiptNo = source.receiptNo;
expenseTrans.transType = TransType.Credit;
expenseTrans.amount = newTrans.bankExpenseAmount;
expenseTrans.debt = 0d;
expenseTrans.credit = expenseTrans.amount;
expenseTrans.excCode = source.excCode;
expenseTrans.excRate = source.excRate;
expenseTrans.excEquivalent = expenseTrans.amount;
expenseTrans.transDate = source.transDate;
expenseTrans.transNo = source.transNo;
expenseTrans.transDir = (expenseTrans.debt.doubleValue() > 0 ? 0 : 1);
expenseTrans.transYear = source.transYear;
expenseTrans.transMonth = source.transMonth;
expenseTrans.description = "MASRAF YOLUYLA YANSIYAN TUTAR (" + Messages.get("enum."+source.right.name()).toUpperCase() + ", FİŞ NO : " + source.receiptNo +")";
expenseTrans.refId = source.id;
expenseTrans.refModule = Module.bank;
if (expenseTrans.id == null) {
expenseTrans.singleSave();
} else {
expenseTrans.singleUpdate();
}
}
if (isTransactionNeeded) Ebean.commitTransaction();
} catch (Exception e) {
if (isTransactionNeeded) Ebean.rollbackTransaction();
log.error(e.getMessage(), e);
if (e instanceof OptimisticLockException) {
return "exception.optimistic.lock";
}
}
return null;
}
public static void remove(AbstractBaseTrans trans) {
Ebean.beginTransaction();
try {
if (trans.refModule != null && ! Module.no.equals(trans.refModule)) {
switch (trans.refModule) {
case contact: {
ContactTrans.findById(trans.refId).singleDelete();
break;
}
case safe: {
SafeTrans.findById(trans.refId).singleDelete();
break;
}
case bank: {
BankTrans.findById(trans.refId).singleDelete();
break;
}
}
}
/*
* Siparis, Irsaliye ve Fatura kayitlari ekstra olarak durum tarihcesi (xxx_trans_status_history) tutarlar, bu kisimda tutulan bu tarihçenin tamamı silinir
*/
String prefixForTransTable = null;
if (trans instanceof OrderTrans) prefixForTransTable = "order";
if (trans instanceof WaybillTrans) prefixForTransTable = "waybill";
if (trans instanceof InvoiceTrans) prefixForTransTable = "invoice";
if (prefixForTransTable != null) {
Ebean.createSqlUpdate("delete from " + prefixForTransTable + "_trans_status_history where trans_id = :trans_id")
.setParameter("trans_id", trans.id)
.execute();
}
/*
* Kasa, Banka ve Cari disindaki moduller ekstra Cari Hareket yansimasi yapmis olabilirler
* varsa bu kayit silinir
*
* @see StockTrans
*/
if (! BASE_MODULE_LIST.contains(trans.right.module)) {
ContactTrans oldExtraTrans = ContactTrans.findByRefIdAndRight(trans.id, trans.right);
if (oldExtraTrans != null) {
oldExtraTrans.singleDelete();
/*
* Pesin faturalar kapama islemi yansitirlar, varsa eger bu kapama hareketi de silinir
*/
if (trans instanceof InvoiceTrans) {
InvoiceTrans asAnInvoiceTrans = (InvoiceTrans) trans;
if (asAnInvoiceTrans.isCash) {
ContactTrans closingTrans = ContactTrans.findByRefIdAndRight(trans.id, Right.CARI_ISLEM_KAPAMA);
if (closingTrans != null) {
closingTrans.singleDelete();
}
}
}
}
}
/*
* Sadece Banka modulu masraf bilgisi varsa ekstra bir hareket yansimasi yapmistir
* bu kayit silinmeli
*/
if (trans instanceof BankTrans) {
BankTrans expenseTrans = BankTrans.findByRefIdAndRight(trans.id, Right.BANK_MASRAF);
if (expenseTrans != null) expenseTrans.singleDelete();
}
trans.singleDelete();
Ebean.commitTransaction();
} catch (Exception e) {
Ebean.rollbackTransaction();
log.error(e.getMessage(), e);
}
}
public static void setTransientFields(AbstractBaseTrans trans) {
AbstractDocTrans refTrans = null;
Contact refContact = null;
Safe refSafe = null;
Bank refBank = null;
ContactTransSource refContactTransSource = null;
SafeTransSource refSafeTransSource = null;
BankTransSource refBankTransSource = null;
BankExpense expense = null;
Double expenseAmount = 0d;
if (trans.refModule == null) return;
switch (trans.refModule) {
case contact: {
refTrans = ContactTrans.findById(trans.refId);
if (refTrans != null) {
refContact = ((ContactTrans) refTrans).contact;
refContactTransSource = ((ContactTrans) refTrans).transSource;
}
break;
}
case safe: {
refTrans = SafeTrans.findById(trans.refId);
if (refTrans != null) {
refSafe = ((SafeTrans) refTrans).safe;
refSafeTransSource = ((SafeTrans) refTrans).transSource;
}
break;
}
case bank: {
refTrans = BankTrans.findById(trans.refId);
if (refTrans != null) {
refBank = ((BankTrans) refTrans).bank;
refBankTransSource = ((BankTrans) refTrans).transSource;
expense = ((BankTrans) refTrans).expense;
expenseAmount = ((BankTrans) refTrans).expenseAmount;
}
break;
}
default: {
refTrans = ContactTrans.findByRefIdAndRight(trans.id, trans.right);
}
}
if (refTrans == null) {
trans.refModule = null;
log.warn("Trans has a reflection link but there is no the same reflection at other side!");
log.warn("---> Right : " + trans.right + " Id : " + trans.id + " Reflection Module : " + trans.refModule);
return;
}
trans.refOldModule = trans.refModule;
trans.refContact = refContact;
trans.refSafe = refSafe;
trans.refBank = refBank;
trans.refContactTransSource = refContactTransSource;
trans.refSafeTransSource = refSafeTransSource;
trans.refBankTransSource = refBankTransSource;
trans.bankExpense = expense;
trans.bankExpenseAmount = expenseAmount;
if (refTrans != null) {
trans.refExcCode = refTrans.excCode;
trans.refExcRate = refTrans.excRate;
trans.refExcEquivalent = refTrans.amount;
}
}
public static Pair checkForRefAccounts(AbstractBaseTrans model) {
return checkForRefAccounts(model, null, null, null);
}
public static Pair checkForRefAccounts(AbstractBaseTrans model, Contact contact) {
return checkForRefAccounts(model, contact, null, null);
}
public static Pair checkForRefAccounts(AbstractBaseTrans model, Safe safe) {
return checkForRefAccounts(model, null, safe, null);
}
public static Pair checkForRefAccounts(AbstractBaseTrans model, Bank bank) {
return checkForRefAccounts(model, null, null, bank);
}
private static Pair checkForRefAccounts(AbstractBaseTrans model, Contact contact, Safe safe, Bank bank) {
Pair result = new Pair(null, null);
if (model.refModule != null) {
switch (model.refModule) {
case contact: {
if (model.refContact == null || model.refContact.id == null) {
result.key = "refContact.name";
result.value = Messages.get("is.not.null", Messages.get("ref.contact"));
} else {
if (contact != null) {
if (contact.id.equals(model.refContact.id)) {
result.key = "refContact.name";
result.value = Messages.get("ref.accounts.same");
}
}
if (Profiles.chosen().gnel_hasExchangeSupport) {
Contact cnt = Contact.findById(model.refContact.id);
if (cnt.excCode != null && ! cnt.excCode.isEmpty() && ! cnt.excCode.equals(model.refExcCode)) {
result.key = "refModule";
result.value = Messages.get("error.exc_code", cnt.name, cnt.excCode);
}
}
}
break;
}
case safe: {
if (model.refSafe == null || model.refSafe.id == null) {
result.key = "refSafe.id";
result.value = Messages.get("is.not.null", Messages.get("ref.safe"));
} else {
if (safe != null) {
if (safe.id.equals(model.refSafe.id)) {
result.key = "refModule";
result.value = Messages.get("ref.accounts.same");
}
}
if (Profiles.chosen().gnel_hasExchangeSupport) {
Safe sfe = Safe.findById(model.refSafe.id);
if (sfe.excCode != null && ! sfe.excCode.isEmpty() && ! sfe.excCode.equals(model.refExcCode)) {
result.key = "refModule";
result.value = Messages.get("error.exc_code", sfe.name, sfe.excCode);
}
}
}
break;
}
case bank: {
if (model.refBank == null || model.refBank.id == null) {
result.key = "refBank.id";
result.value = Messages.get("is.not.null", Messages.get("ref.bank"));
} else {
if (bank != null) {
if (bank.id.equals(model.refBank.id)) {
result.key = "refModule";
result.value = Messages.get("ref.accounts.same");
}
}
if (Profiles.chosen().gnel_hasExchangeSupport) {
Bank bnk = Bank.findById(model.refBank.id);
if (bnk.excCode != null && ! bnk.excCode.isEmpty() && ! bnk.excCode.equals(model.refExcCode)) {
result.key = "refModule";
result.value = Messages.get("error.exc_code", bnk.name, bnk.excCode);
}
}
}
break;
}
}
}
if (contact != null && contact.id != null && Profiles.chosen().gnel_hasExchangeSupport) {
Contact cnt = Contact.findById(contact.id);
if (cnt.excCode != null && ! cnt.excCode.isEmpty() && ! cnt.excCode.equals(model.excCode)) {
result.key = "amount";
result.value = Messages.get("error.exc_code", cnt.name, cnt.excCode);
}
}
if (safe != null && Profiles.chosen().gnel_hasExchangeSupport) {
Safe sfe = Safe.findById(safe.id);
if (sfe.excCode != null && ! sfe.excCode.isEmpty() && ! sfe.excCode.equals(model.excCode)) {
result.key = "amount";
result.value = Messages.get("error.exc_code", sfe.name, sfe.excCode);
}
}
if (bank != null && Profiles.chosen().gnel_hasExchangeSupport) {
Bank bnk = Bank.findById(bank.id);
if (bnk.excCode != null && ! bnk.excCode.isEmpty() && ! bnk.excCode.equals(model.excCode)) {
result.key = "amount";
result.value = Messages.get("error.exc_code", bnk.name, bnk.excCode);
}
}
return result;
}
}