Skip to content

Commit

Permalink
Add conversion rate for order and payment
Browse files Browse the repository at this point in the history
  • Loading branch information
yamelsenih committed Nov 9, 2021
1 parent 3aa8f6c commit 19df7d4
Show file tree
Hide file tree
Showing 3 changed files with 167 additions and 62 deletions.
126 changes: 121 additions & 5 deletions src/main/java/org/spin/base/util/ConvertUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,15 @@
import java.util.Optional;
import java.util.Properties;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;

import org.compiere.model.I_AD_Element;
import org.compiere.model.I_AD_Ref_List;
import org.compiere.model.I_AD_User;
import org.compiere.model.I_C_Bank;
import org.compiere.model.I_C_Campaign;
import org.compiere.model.I_C_ConversionType;
import org.compiere.model.I_C_Currency;
import org.compiere.model.I_C_Order;
import org.compiere.model.I_C_POSKeyLayout;
import org.compiere.model.MAttachment;
Expand All @@ -49,8 +53,10 @@
import org.compiere.model.MOrderLine;
import org.compiere.model.MOrg;
import org.compiere.model.MOrgInfo;
import org.compiere.model.MPOS;
import org.compiere.model.MPOSKey;
import org.compiere.model.MPOSKeyLayout;
import org.compiere.model.MPayment;
import org.compiere.model.MPriceList;
import org.compiere.model.MProduct;
import org.compiere.model.MProductCategory;
Expand Down Expand Up @@ -87,6 +93,7 @@
import org.spin.grpc.util.Order;
import org.spin.grpc.util.OrderLine;
import org.spin.grpc.util.Organization;
import org.spin.grpc.util.Payment;
import org.spin.grpc.util.PriceList;
import org.spin.grpc.util.Product;
import org.spin.grpc.util.Region;
Expand All @@ -98,6 +105,7 @@
import org.spin.grpc.util.Value;
import org.spin.grpc.util.Warehouse;
import org.spin.grpc.util.ChatEntry.ModeratorStatus;
import org.spin.model.I_C_PaymentMethod;
import org.spin.model.MADAttachmentReference;
import org.spin.util.AttachmentUtil;
import org.spin.util.VueStoreFrontUtil;
Expand Down Expand Up @@ -483,6 +491,16 @@ public static Order.Builder convertOrder(MOrder order) {
MRefList reference = MRefList.get(Env.getCtx(), MOrder.DOCSTATUS_AD_REFERENCE_ID, order.getDocStatus(), null);
MPriceList priceList = MPriceList.get(Env.getCtx(), order.getM_PriceList_ID(), order.get_TrxName());
BigDecimal baseAmount = Arrays.asList(order.getLines()).stream().map(orderLine -> Optional.ofNullable(orderLine.getPriceList()).orElse(Env.ZERO)).reduce(BigDecimal.ZERO, BigDecimal::add);
Optional<BigDecimal> paidAmount = MPayment.getOfOrder(order).stream().map(payment -> getConvetedAmount(order, payment, payment.getPayAmt())).collect(Collectors.reducing(BigDecimal::add));
BigDecimal grandTotal = order.getGrandTotal();
BigDecimal totalLines = order.getTotalLines();
BigDecimal paymentAmount = Env.ZERO;
if(paidAmount.isPresent()) {
paymentAmount = paidAmount.get();
}
BigDecimal openAmount = (grandTotal.subtract(paymentAmount).compareTo(Env.ZERO) < 0? Env.ZERO: grandTotal.subtract(paymentAmount));
BigDecimal refundAmount = (grandTotal.subtract(paymentAmount).compareTo(Env.ZERO) > 0? Env.ZERO: grandTotal.subtract(paymentAmount).negate());
BigDecimal displayCurrencyRate = getDisplayConversionRateFromOrder(order);
// Convert
return builder
.setUuid(ValueUtil.validateNull(order.getUUID()))
Expand All @@ -499,12 +517,110 @@ public static Order.Builder convertOrder(MOrder order) {
.setPriceList(ConvertUtil.convertPriceList(MPriceList.get(Env.getCtx(), order.getM_PriceList_ID(), order.get_TrxName())))
.setWarehouse(convertWarehouse(order.getM_Warehouse_ID()))
.setIsDelivered(order.isDelivered())
.setDiscountAmount(ValueUtil.getDecimalFromBigDecimal(order.getTotalLines().subtract(Optional.ofNullable(baseAmount).orElse(Env.ZERO).setScale(priceList.getStandardPrecision(), BigDecimal.ROUND_HALF_UP))))
.setTaxAmount(ValueUtil.getDecimalFromBigDecimal(order.getGrandTotal().subtract(order.getTotalLines()).setScale(priceList.getStandardPrecision(), BigDecimal.ROUND_HALF_UP)))
.setTotalLines(ValueUtil.getDecimalFromBigDecimal(order.getTotalLines().setScale(priceList.getStandardPrecision(), BigDecimal.ROUND_HALF_UP)))
.setGrandTotal(ValueUtil.getDecimalFromBigDecimal(order.getGrandTotal().setScale(priceList.getStandardPrecision(), BigDecimal.ROUND_HALF_UP)))
.setDiscountAmount(ValueUtil.getDecimalFromBigDecimal(totalLines.subtract(Optional.ofNullable(baseAmount).orElse(Env.ZERO).setScale(priceList.getStandardPrecision(), BigDecimal.ROUND_HALF_UP))))
.setTaxAmount(ValueUtil.getDecimalFromBigDecimal(grandTotal.subtract(totalLines).setScale(priceList.getStandardPrecision(), BigDecimal.ROUND_HALF_UP)))
.setTotalLines(ValueUtil.getDecimalFromBigDecimal(totalLines.setScale(priceList.getStandardPrecision(), BigDecimal.ROUND_HALF_UP)))
.setGrandTotal(ValueUtil.getDecimalFromBigDecimal(grandTotal.setScale(priceList.getStandardPrecision(), BigDecimal.ROUND_HALF_UP)))
.setDisplayCurrencyRate(ValueUtil.getDecimalFromBigDecimal(displayCurrencyRate.setScale(priceList.getStandardPrecision(), BigDecimal.ROUND_HALF_UP)))
.setPaymentAmount(ValueUtil.getDecimalFromBigDecimal(paymentAmount.setScale(priceList.getStandardPrecision(), BigDecimal.ROUND_HALF_UP)))
.setOpenAmount(ValueUtil.getDecimalFromBigDecimal(openAmount.setScale(priceList.getStandardPrecision(), BigDecimal.ROUND_HALF_UP)))
.setRefundAmount(ValueUtil.getDecimalFromBigDecimal(refundAmount.setScale(priceList.getStandardPrecision(), BigDecimal.ROUND_HALF_UP)))
.setDateOrdered(ValueUtil.convertDateToString(order.getDateOrdered()))
.setCustomer(convertCustomer((MBPartner) order.getC_BPartner()));
.setCustomer(convertCustomer((MBPartner) order.getC_BPartner()))
.setCampaignUuid(ValueUtil.validateNull(RecordUtil.getUuidFromId(I_C_Campaign.Table_Name, order.getC_Campaign_ID())));
}

/**
* Get Converted Amount based on Order currency
* @param order
* @param payment
* @return
* @return BigDecimal
*/
private static BigDecimal getConvetedAmount(MOrder order, MPayment payment, BigDecimal amount) {
if(payment.getC_Currency_ID() == order.getC_Currency_ID()
|| amount == null
|| amount.compareTo(Env.ZERO) == 0) {
return amount;
}
BigDecimal convertedAmount = MConversionRate.convert(payment.getCtx(), amount, payment.getC_Currency_ID(), order.getC_Currency_ID(), payment.getDateAcct(), payment.getC_ConversionType_ID(), payment.getAD_Client_ID(), payment.getAD_Org_ID());
//
return Optional.ofNullable(convertedAmount).orElse(Env.ZERO);
}

/**
* Get Display Currency rate from Sales Order
* @param order
* @return
* @return BigDecimal
*/
private static BigDecimal getDisplayConversionRateFromOrder(MOrder order) {
MPOS pos = MPOS.get(order.getCtx(), order.getC_POS_ID());
if(order.getC_Currency_ID() == pos.get_ValueAsInt("DisplayCurrency_ID")
|| pos.get_ValueAsInt("DisplayCurrency_ID") <= 0) {
return Env.ONE;
}
BigDecimal conversionRate = MConversionRate.getRate(order.getC_Currency_ID(), pos.get_ValueAsInt("DisplayCurrency_ID"), order.getDateAcct(), order.getC_ConversionType_ID(), order.getAD_Client_ID(), order.getAD_Org_ID());
//
return Optional.ofNullable(conversionRate).orElse(Env.ZERO);
}

/**
* Convert payment
* @param payment
* @return
*/
public static Payment.Builder convertPayment(MPayment payment) {
Payment.Builder builder = Payment.newBuilder();
if(payment == null) {
return builder;
}
//
MRefList reference = MRefList.get(Env.getCtx(), MPayment.DOCSTATUS_AD_REFERENCE_ID, payment.getDocStatus(), payment.get_TrxName());
int presicion = MCurrency.getStdPrecision(payment.getCtx(), payment.getC_Currency_ID());
BigDecimal orderConversionRate = getOrderConversionRateFromPayment(payment);
// Convert
builder
.setId(payment.getC_Payment_ID())
.setUuid(ValueUtil.validateNull(payment.getUUID()))
.setOrderUuid(ValueUtil.validateNull(RecordUtil.getUuidFromId(I_C_Order.Table_Name, payment.getC_Order_ID())))
.setDocumentNo(ValueUtil.validateNull(payment.getDocumentNo()))
.setTenderTypeCode(ValueUtil.validateNull(payment.getTenderType()))
.setPaymentMethodUuid(ValueUtil.validateNull(RecordUtil.getUuidFromId(I_C_PaymentMethod.Table_Name, payment.get_ValueAsInt("C_PaymentMethod_ID"))))
.setReferenceNo(ValueUtil.validateNull(Optional.ofNullable(payment.getCheckNo()).orElse(payment.getDocumentNo())))
.setDescription(ValueUtil.validateNull(payment.getDescription()))
.setAmount(ValueUtil.getDecimalFromBigDecimal(payment.getPayAmt().setScale(presicion, BigDecimal.ROUND_HALF_UP)))
.setOrderCurrencyRate(ValueUtil.getDecimalFromBigDecimal(orderConversionRate))
.setBankUuid(ValueUtil.validateNull(RecordUtil.getUuidFromId(I_C_Bank.Table_Name, payment.getC_Bank_ID())))
.setCustomer(ConvertUtil.convertCustomer((MBPartner) payment.getC_BPartner()))
.setCurrencyUuid(RecordUtil.getUuidFromId(I_C_Currency.Table_Name, payment.getC_Currency_ID()))
.setPaymentDate(ValueUtil.convertDateToString(payment.getDateTrx()))
.setIsRefund(!payment.isReceipt())
.setPaymentAccountDate(ValueUtil.convertDateToString(payment.getDateAcct()))
.setDocumentStatus(ConvertUtil.convertDocumentStatus(ValueUtil.validateNull(payment.getDocStatus()),
ValueUtil.validateNull(ValueUtil.getTranslation(reference, I_AD_Ref_List.COLUMNNAME_Name)),
ValueUtil.validateNull(ValueUtil.getTranslation(reference, I_AD_Ref_List.COLUMNNAME_Description))))
;
return builder;
}

/**
* Get Order conversion rate for payment
* @param payment
* @return
* @return BigDecimal
*/
private static BigDecimal getOrderConversionRateFromPayment(MPayment payment) {
if(payment.getC_Order_ID() <= 0) {
return Env.ONE;
}
MOrder order = (MOrder) payment.getC_Order();
if(payment.getC_Currency_ID() == order.getC_Currency_ID()) {
return Env.ONE;
}
BigDecimal conversionRate = MConversionRate.getRate(payment.getC_Currency_ID(), order.getC_Currency_ID(), payment.getDateAcct(), payment.getC_ConversionType_ID(), payment.getAD_Client_ID(), payment.getAD_Org_ID());
//
return Optional.ofNullable(conversionRate).orElse(Env.ZERO);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
import org.compiere.model.I_C_BP_Group;
import org.compiere.model.I_C_BPartner;
import org.compiere.model.I_C_Bank;
import org.compiere.model.I_C_Campaign;
import org.compiere.model.I_C_Charge;
import org.compiere.model.I_C_City;
import org.compiere.model.I_C_ConversionType;
Expand Down Expand Up @@ -78,7 +79,6 @@
import org.compiere.model.MProduct;
import org.compiere.model.MProductPrice;
import org.compiere.model.MProductPricing;
import org.compiere.model.MRefList;
import org.compiere.model.MStorage;
import org.compiere.model.MTable;
import org.compiere.model.MTax;
Expand Down Expand Up @@ -442,7 +442,7 @@ public void createPayment(CreatePaymentRequest request, StreamObserver<Payment>
request.getClientRequest().getLanguage(),
request.getClientRequest().getOrganizationUuid(),
request.getClientRequest().getWarehouseUuid());
Payment.Builder payment = convertPayment(createPayment(request));
Payment.Builder payment = ConvertUtil.convertPayment(createPayment(request));
responseObserver.onNext(payment.build());
responseObserver.onCompleted();
} catch (Exception e) {
Expand All @@ -466,7 +466,7 @@ public void updatePayment(UpdatePaymentRequest request, StreamObserver<Payment>
request.getClientRequest().getLanguage(),
request.getClientRequest().getOrganizationUuid(),
request.getClientRequest().getWarehouseUuid());
Payment.Builder payment = convertPayment(updatePayment(request));
Payment.Builder payment = ConvertUtil.convertPayment(updatePayment(request));
responseObserver.onNext(payment.build());
responseObserver.onCompleted();
} catch (Exception e) {
Expand Down Expand Up @@ -2557,7 +2557,7 @@ private ListOrdersResponse.Builder listOrders(ListOrdersRequest request) {
int orgId = Env.getAD_Org_ID(Env.getCtx());
boolean isWithAisleSeller = M_Element.get(Env.getCtx(), "IsAisleSeller") != null;
if(isWithAisleSeller
&& request.getIsAisleSeller()) {
&& request.getIsOnlyAisleSeller()) {
whereClause.append("(C_Order.C_POS_ID = ? OR (C_Order.AD_Org_ID = ? AND EXISTS(SELECT 1 FROM C_POS p WHERE p.C_POS_ID = C_Order.C_POS_ID AND p.IsAisleSeller = 'Y')))");
parameters.add(posId);
parameters.add(orgId);
Expand Down Expand Up @@ -2593,13 +2593,20 @@ private ListOrdersResponse.Builder listOrders(ListOrdersRequest request) {
parameters.add(openAmount);
parameters.add(openAmount);
}
whereClause.append(" AND Processed = ?");
parameters.add(request.getIsProcessed()? "Y": "N");
if(request.getIsOnlyProcessed()) {
whereClause.append(" AND Processed = ?");
parameters.add("Y");
}
// Is Invoiced
if(request.getIsInvoiced()
|| request.getIsPaid()) {
whereClause.append(" AND EXISTS(SELECT 1 FROM C_Invoice i WHERE i.C_Order_ID = C_Order.C_Order_ID AND i.DocStatus IN('CO', 'CL') AND i.IsPaid = ?)");
parameters.add(request.getIsPaid()? "Y": "N");
if(request.getIsWaitingForInvoice()) {
whereClause.append(" AND NOT EXISTS(SELECT 1 FROM C_Invoice i WHERE i.C_Order_ID = C_Order.C_Order_ID AND i.DocStatus IN('CO', 'CL'))");
}
// for payment
if(request.getIsWaitingForPay()) {
whereClause.append(" AND NOT EXISTS(SELECT 1 FROM C_Payment p WHERE p.C_Order_ID = C_Order.C_Order_ID)");
}
if(request.getIsWaitingForShipment()) {
whereClause.append(" AND NOT EXISTS(SELECT 1 FROM M_InOut io WHERE io.C_Order_ID = C_Order.C_Order_ID AND io.DocStatus IN('CO', 'CL'))");
}
// Date Order From
if(!Util.isEmpty(request.getDateOrderedFrom())) {
Expand Down Expand Up @@ -2685,7 +2692,7 @@ private ListPaymentsResponse.Builder listPayments(ListPaymentsRequest request) {
.setLimit(limit, offset)
.<MPayment>list()
.forEach(payment -> {
builder.addPayments(convertPayment(payment));
builder.addPayments(ConvertUtil.convertPayment(payment));
});
//
builder.setRecordCount(count);
Expand Down Expand Up @@ -2802,6 +2809,10 @@ private MOrder updateOrder(UpdateOrderRequest request) {
// Warehouse
int warehouseId = 0;
int priceListId = 0;
int campaignId = RecordUtil.getIdFromUuid(I_C_Campaign.Table_Name, request.getCampaignUuid(), transactionName);
if(campaignId > 0 && campaignId != salesOrder.getC_Campaign_ID()) {
salesOrder.setC_Campaign_ID(campaignId);
}
if(!Util.isEmpty(request.getWarehouseUuid())) {
warehouseId = RecordUtil.getIdFromUuid(I_M_Warehouse.Table_Name, request.getWarehouseUuid(), transactionName);
}
Expand Down Expand Up @@ -3447,6 +3458,7 @@ private Order.Builder createOrder(CreateOrderRequest request) {
salesOrder.setDateAcct(RecordUtil.getDate());
salesOrder.setDatePromised(RecordUtil.getDate());
}
// Set campaign
// Default values
salesOrder.setIsSOTrx(true);
salesOrder.setAD_Org_ID(pos.getAD_Org_ID());
Expand Down Expand Up @@ -3499,6 +3511,10 @@ private Order.Builder createOrder(CreateOrderRequest request) {
if(pos.get_ValueAsInt(MOrder.COLUMNNAME_C_ConversionType_ID) > 0) {
salesOrder.setC_ConversionType_ID(pos.get_ValueAsInt(MOrder.COLUMNNAME_C_ConversionType_ID));
}
int campaignId = RecordUtil.getIdFromUuid(I_C_Campaign.Table_Name, request.getCampaignUuid(), transactionName);
if(campaignId > 0 && campaignId != salesOrder.getC_Campaign_ID()) {
salesOrder.setC_Campaign_ID(campaignId);
}
// Set business partner
setBPartner(pos, salesOrder, request.getCustomerUuid(), request.getSalesRepresentativeUuid(), transactionName);
maybeOrder.set(salesOrder);
Expand Down Expand Up @@ -3640,42 +3656,6 @@ private void setBPartner(MPOS pos, MOrder salesOrder, String businessPartnerUuid
});
}

/**
* Convert payment
* @param payment
* @return
*/
private Payment.Builder convertPayment(MPayment payment) {
Payment.Builder builder = Payment.newBuilder();
if(payment == null) {
return builder;
}
//
MRefList reference = MRefList.get(Env.getCtx(), MPayment.DOCSTATUS_AD_REFERENCE_ID, payment.getDocStatus(), null);
// Convert
builder
.setId(payment.getC_Payment_ID())
.setUuid(ValueUtil.validateNull(payment.getUUID()))
.setOrderUuid(ValueUtil.validateNull(RecordUtil.getUuidFromId(I_C_Order.Table_Name, payment.getC_Order_ID())))
.setDocumentNo(ValueUtil.validateNull(payment.getDocumentNo()))
.setTenderTypeCode(ValueUtil.validateNull(payment.getTenderType()))
.setPaymentMethodUuid(ValueUtil.validateNull(RecordUtil.getUuidFromId(I_C_PaymentMethod.Table_Name, payment.get_ValueAsInt("C_PaymentMethod_ID"))))
.setReferenceNo(ValueUtil.validateNull(Optional.ofNullable(payment.getCheckNo()).orElse(payment.getDocumentNo())))
.setDescription(ValueUtil.validateNull(payment.getDescription()))
.setAmount(ValueUtil.getDecimalFromBigDecimal(payment.getPayAmt()))
.setBankUuid(ValueUtil.validateNull(RecordUtil.getUuidFromId(I_C_Bank.Table_Name, payment.getC_Bank_ID())))
.setCustomer(ConvertUtil.convertCustomer((MBPartner) payment.getC_BPartner()))
.setCurrencyUuid(RecordUtil.getUuidFromId(I_C_Currency.Table_Name, payment.getC_Currency_ID()))
.setPaymentDate(ValueUtil.convertDateToString(payment.getDateTrx()))
.setIsRefund(!payment.isReceipt())
.setPaymentAccountDate(ValueUtil.convertDateToString(payment.getDateAcct()))
.setDocumentStatus(ConvertUtil.convertDocumentStatus(ValueUtil.validateNull(payment.getDocStatus()),
ValueUtil.validateNull(ValueUtil.getTranslation(reference, I_AD_Ref_List.COLUMNNAME_Name)),
ValueUtil.validateNull(ValueUtil.getTranslation(reference, I_AD_Ref_List.COLUMNNAME_Description))))
;
return builder;
}

/**
* Update payment if is required
* @param request
Expand Down
29 changes: 19 additions & 10 deletions src/main/proto/point_of_sales.proto
Original file line number Diff line number Diff line change
Expand Up @@ -617,17 +617,18 @@ message ListOrdersRequest {
string business_partner_uuid = 4;
Decimal grand_total = 5;
Decimal open_amount = 6;
bool is_paid = 7;
bool is_processed = 8;
bool is_aisle_seller = 9;
bool is_invoiced = 10;
string date_ordered_from = 11;
string date_ordered_to = 12;
string sales_representative_uuid = 13;
int32 page_size = 14;
string page_token = 15;
bool is_waiting_for_pay = 7;
bool is_only_processed = 8;
bool is_only_aisle_seller = 9;
bool is_waiting_for_invoice = 10;
bool is_waiting_for_shipment = 11;
string date_ordered_from = 12;
string date_ordered_to = 13;
string sales_representative_uuid = 14;
int32 page_size = 15;
string page_token = 16;
// Query
Criteria criteria = 16;
Criteria criteria = 17;
}

// List Order Lines Response
Expand Down Expand Up @@ -717,6 +718,7 @@ message CreateOrderRequest {
string price_list_uuid = 5;
string warehouse_uuid = 6;
string sales_representative_uuid = 7;
string campaign_uuid = 8;
}

// Request for process a order
Expand Down Expand Up @@ -813,6 +815,7 @@ message Payment {
string currency_uuid = 17;
bool is_refund = 18;
string payment_method_uuid = 19;
Decimal order_currency_rate = 20;
}

// Request for delete a order
Expand Down Expand Up @@ -850,6 +853,7 @@ message UpdateOrderRequest {
string price_list_uuid = 6;
string warehouse_uuid = 7;
string description = 8;
string campaign_uuid = 9;
}

// Request for update a order line
Expand Down Expand Up @@ -895,6 +899,11 @@ message Order {
bool is_delivered = 16;
string order_reference = 17;
string description = 18;
string campaign_uuid = 19;
Decimal display_currency_rate = 20;
Decimal open_amount = 21;
Decimal payment_amount = 22;
Decimal refund_amount = 23;
}

// Sales Order Line
Expand Down

0 comments on commit 19df7d4

Please sign in to comment.