Description
Split the PaySelLine to batches by Supplier Code ,Currency, Min & Max Batch size(SysProperty).
Parameters
oiReturnStatus | output | integer | Return status of the method. |
Internal usage
QadFinancials
program code (program1/bpaymentselection.p)
/* ===================================================================================================================== */
/* Assign GroupUnionType to each PaySelLine: the combination of CreditorCode, InvoiceCurrencyCode and PayFormatTypeCode. */
/* ===================================================================================================================== */
for each tPaySelLine:
define variable i as integer no-undo.
assign tPaySelLine.tcGroupUnionType = tPaySelLine.tcGroupUnionType + tPaySelLine.tcCreditorCode.
if length(tPaySelLine.tcCreditorCode, "CHARACTER") < 8 then
do:
viAddSpaceNum = 8 - length(tPaySelLine.tcCreditorCode, "CHARACTER").
repeat i = 1 to viAddSpaceNum:
assign tPaySelLine.tcGroupUnionType = tPaySelLine.tcGroupUnionType + " ".
end.
end.
assign tPaySelLine.tcGroupUnionType = tPaySelLine.tcGroupUnionType + tPaySelLine.tcInvoiceCurrencyCode.
if length(tPaySelLine.tcInvoiceCurrencyCode, "CHARACTER") < 3 then
do:
viAddSpaceNum = 3 - length(tPaySelLine.tcInvoiceCurrencyCode, "CHARACTER").
repeat i = 1 to viAddSpaceNum:
assign tPaySelLine.tcGroupUnionType = tPaySelLine.tcGroupUnionType + " ".
end.
end.
assign tPaySelLine.tcGroupUnionType = tPaySelLine.tcGroupUnionType + tPaySelLine.PayFormatTypeCode.
if length(tPaySelLine.PayFormatTypeCode, "CHARACTER") < 20 then
do:
viAddSpaceNum = 20 - length(tPaySelLine.tcCreditorCode, "CHARACTER").
repeat i = 1 to viAddSpaceNum:
assign tPaySelLine.tcGroupUnionType = tPaySelLine.tcGroupUnionType + " ".
end.
end.
end.
empty temp-table tPaySelLineDS.
/* ================================================== */
/* Copy tPaySelLine to tPaySelLineDS for modification. */
/* ================================================== */
assign viGroupLinesCnt = 0.
for each tPaySelLine where tPaySelLine.PaySelLineIsConfirmed <> yes
break by tPaySelLine.tcGroupUnionType by tPaySelLine.PaySelLineParentObject_ID:
viGroupLinesCnt = viGroupLinesCnt + 1.
create tPaySelLineDS.
assign tPaySelLineDS.tibMaster_ID = viGroupLinesCnt
tPaySelLineDS.tibPaySel_ID = tPaySelLine.PaySel_ID
tPaySelLineDS.tibPaySelLine_ID = tPaySelLine.PaySelLine_ID
tPaySelLineDS.tcbGroupUnionType = tPaySelLine.tcGroupUnionType
tPaySelLineDS.tdbPaySelLineAmountTC = 0 - tPaySelLine.tdInvoiceBalanceTCSigned
tPaySelLineDS.tibPaySelLineParentObject_ID = tPaySelLine.PaySelLineParentObject_ID.
end.
/* ========================================================================================================= */
/* Group PaySelLine by GroupUnionType. Assign GroupID and calculate the number of PaySelLine for each group. */
/* ========================================================================================================= */
empty temp-table tInvoiceGroup.
assign viGroupNum = 1.
for each tPaySelLine where tPaySelLine.PaySelLineIsConfirmed <> yes
break by tPaySelLine.tcGroupUnionType:
if first-of(tPaySelLine.tcGroupUnionType) then
do:
viGroupLinesCnt = 0.
for each tPaySelLineDS where tPaySelLineDS.tcbGroupUnionType = tPaySelLine.tcGroupUnionType:
viGroupLinesCnt = viGroupLinesCnt + 1.
end.
create tInvoiceGroup.
assign tInvoiceGroup.tiGroupID = viGroupNum * 10000
tInvoiceGroup.tiGroupLinesCnt = viGroupLinesCnt.
viGroupNum = viGroupNum + 1.
end.
end.
assign viBatchCnt = 0
viCurrInvoiceGroupID = 0.
/* ============ */
/* Output table */
/* ============ */
empty temp-table tSupplierInvoiceGroups.
/* ======================================================================================================================= */
/* BatchLoop is the main loop that keeps on fetching the next available group as the current group and starts a new batch. */
/* By BatchLoop, we split groups into small batches whose sizes are possibly fallen between MinBatchSize and MaxBatchSize. */
/* ======================================================================================================================= */
BatchLoop:
Do while true:
assign viBatchCnt = viBatchCnt + 1 /* At the beginning of main loop, increase the batch count viBatchCnt and start a new batch. */
viBatchLinesCnt = 0 /* The new batch has 0 lines. */
vlStartNextBatch = false /* No need to start next batch because the new batch is not filled yet. */
vdTotalAmount = 0. /* vdTotalAmount is a decimal to calculate the amount of several PaySelLines. */
Do while true:
assign vlGroupFound = false. /* vlGroupFound is a flag to show if there is a next group available in the order of GroupIndex. */
/* If there exists a next group, assign its ID and size to viCurrInvoiceGroupID and viCurrInvoiceGroupLinesCnt */
for first tInvoiceGroup where tInvoiceGroup.tiGroupID > viCurrInvoiceGroupID use-index GroupIndex:
assign viCurrInvoiceGroupID = tInvoiceGroup.tiGroupID
viCurrInvoiceGroupLinesCnt = tInvoiceGroup.tiGroupLinesCnt.
vlGroupFound = true.
end.
if vlGroupFound = false then do: /* If there is no available group, the main loop ends and splitting is over. */
leave BatchLoop.
end.
if viCurrInvoiceGroupLinesCnt = 0 then next. /* If the group found is empty
, go and find next available group. */
/* If current group is added, current batch size will be less than or equal to MaxBatchSize */
if viBatchLinesCnt + viCurrInvoiceGroupLinesCnt <= viMaxBatchSize then
do:
find tInvoiceGroup where tInvoiceGroup.tiGroupID = viCurrInvoiceGroupID.
assign tInvoiceGroup.tiBatchNum = viBatchCnt.
assign viBatchLinesCnt = viBatchLinesCnt + viCurrInvoiceGroupLinesCnt.
for each tPaySelLineDS where tPaySelLineDS.tibMaster_ID > viTotalLinesCnt and tPaySelLineDS.tibMaster_ID <= viTotalLinesCnt + viCurrInvoiceGroupLinesCnt
break by tPaySelLineDS.tcbGroupUnionType:
create tSupplierInvoiceGroups.
assign tSupplierInvoiceGroups.tiPaySel_ID = tPaySelLineDS.tibPaySel_ID
tSupplierInvoiceGroups.tiPaymentSelectionLineID = tPaySelLineDS.tibPaySelLine_ID
tSupplierInvoiceGroups.tiGroupNumber = viBatchCnt
tSupplierInvoiceGroups.tiPaySelLineParentObject_ID = tPaySelLineDS.tibPaySelLineParentObject_ID.
end.
viTotalLinesCnt = viTotalLinesCnt + viCurrInvoiceGroupLinesCnt.
end.
/* Current group is a single group whose size is greater than MaxBatchSize. Or if current group is added, current batch size will exceed MaxBatchSize. */
else
do:
if viBatchLinesCnt + viCurrInvoiceGroupLinesCnt > viMaxBatchSize then
do:
if vlStartNextBatch = true then /* vlStartNextBatch indicates the necessity of start a new batch. */
do:
assign viCurrInvoiceGroupID = viCurrInvoiceGroupID - 1.
next BatchLoop.
end.
/* Fetch the current group. */
find tInvoiceGroup where tInvoiceGroup.tiGroupID = viCurrInvoiceGroupID.
if viBatchLinesCnt = 0 then do: /* A single group size larger than MaxBatchSize */
/* Check if the group is divisible. */
vdTotalAmount = 0.
for each tPaySelLineDS where tPaySelLineDS.tibMaster_ID > viTotalLinesCnt and tPaySelLineDS.tibMaster_ID <= viTotalLinesCnt + viCurrInvoiceGroupLinesCnt
break by tPaySelLineDS.tcbGroupUnionType:
vdTotalAmount = vdTotalAmount + tPaySelLineDS.tdbPaySelLineAmountTC.
viCount = viCount + 1.
if viCount modulo viMaxBatchSize = 0 or viCount = viCurrInvoiceGroupLinesCnt then do:
if vdTotalAmount < 0 then do:
vlSplitable = false.
leave.
end.
else do:
vdTotalAmount = 0.
end.
end.
end.
/* If not divisible, the whole group is assigned to one batch, then start next main loop. */
if not vlSplitable then do:
for each tPaySelLineDS where tPaySelLineDS.tibMaster_ID > viTotalLinesCnt and tPaySelLineDS.tibMaster_ID <= viTotalLinesCnt + viCurrInvoiceGroupLinesCnt
break by tPaySelLineDS.tcbGroupUnionType:
create tSupplierInvoiceGroups.
assign tSupplierInvoiceGroups.tiPaySel_ID = tPaySelLineDS.tibPaySel_ID
tSupplierInvoiceGroups.tiPaymentSelectionLineID = tPaySelLineDS.tibPaySelLine_ID
tSupplierInvoiceGroups.tiGroupNumber = viBatchCnt
tSupplierInvoiceGroups.tiPaySelLineParentObject_ID = tPaySelLineDS.tibPaySelLineParentObject_ID.
end.
viTotalLinesCnt = viTotalLinesCnt + viCurrInvoiceGroupLinesCnt.
next BatchLoop.
end.
end.
else do: /* Current batch size + curent group size exceeds MaxBatchSize, try to split the group. */
/* Check if the amount of first (viMaxBatchSize - viBatchLinesCnt) PaySelLines is > 0 after merge. If not, cancel the merge. */
vdTotalAmount = 0.
viStartLine = viTotalLinesCnt.
viUsedLines = viCurrInvoiceGroupLinesCnt.
for each tPaySelLineDS where tPaySelLineDS.tibMaster_ID > viStartLine and tPaySelLineDS.tibMaster_ID <= viStartLine + viUsedLines
break by tPaySelLineDS.tcbGroupUnionType:
vdTotalAmount = vdTotalAmount + tPaySelLineDS.tdbPaySelLineAmountTC.
end.
if vdTotalAmount < 0 then do:
viCurrInvoiceGroupID = viCurrInvoiceGroupID - 1.
next BatchLoop.
end.
/* Check if the amount of the remainder is still > 0. If not, cancel the merge. */
vdTotalAmount = 0.
viStartLine = viTotalLinesCnt - viBatchLinesCnt + viMaxBatchSize.
viUsedLines = viCurrInvoiceGroupLinesCnt - viMaxBatchSize + viBatchLinesCnt.
for each tPaySelLineDS where tPaySelLineDS.tibMaster_ID > viStartLine and tPaySelLineDS.tibMaster_ID <= viStartLine + viUsedLines
break by tPaySelLineDS.tcbGroupUnionType:
vdTotalAmount = vdTotalAmount + tPaySelLineDS.tdbPaySelLineAmountTC.
end.
if vdTotalAmount < 0 then do:
viCurrInvoiceGroupID = viCurrInvoiceGroupID - 1.
next BatchLoop.
end.
end.
/* After split, assign first (viMaxBatchSize - viBatchLinesCnt) PaySelLines in current group to this batch. */
assign tInvoiceGroup.tiBatchNum = viBatchCnt
tInvoiceGroup.tiGroupLinesCnt = viMaxBatchSize - viBatchLinesCnt.
for each tPaySelLineDS where tPaySelLineDS.tibMaster_ID > viTotalLinesCnt and tPaySelLineDS.tibMaster_ID <= viTotalLinesCnt + tInvoiceGroup.tiGroupLinesCnt
break by tPaySelLineDS.tcbGroupUnionType:
create tSupplierInvoiceGroups.
assign tSupplierInvoiceGroups.tiPaySel_ID = tPaySelLineDS.tibPaySel_ID
tSupplierInvoiceGroups.tiPaymentSelectionLineID = tPaySelLineDS.tibPaySelLine_ID
tSupplierInvoiceGroups.tiGroupNumber = viBatchCnt
tSupplierInvoiceGroups.tiPaySelLineParentObject_ID = tPaySelLineDS.tibPaySelLineParentObject_ID.
end.
viTotalLinesCnt = viTotalLinesCnt + tInvoiceGroup.tiGroupLinesCnt.
/* Insert a new group with size of the remainder right after the current group. */
create tInvoiceGroup.
assign tInvoiceGroup.tiGroupID = viCurrInvoiceGroupID + 1
tInvoiceGroup.tiGroupLinesCnt = viBatchLinesCnt + viCurrInvoiceGroupLinesCnt - viMaxBatchSize.
next BatchLoop. /* Start next batch */
end.
end.
/* When current batch size reach MinBatchSize, it is OK to start a new batch. As the loop goes to next group, */
/* if that group’s + current batch size exceeds MaxBatchSize, it will goes to the ELSE block and first check if */
/* vlStartNextBatch is true. If true, go to next batch loop and start a new batch. */
if viBatchLinesCnt >= viMinBatchSize then
assign vlStartNextBatch = true.
end. /* Next invoiceGroup */
end. /* Next batchLoop */
/* Pull the payment selection line of the same invoice into one batch */
for each tSupplierInvoiceGroups
break by tSupplierInvoiceGroups.tiGroupNumber
by tSupplierInvoiceGroups.tiPaySelLineParentObject_ID:
if last-of(tSupplierInvoiceGroups.tiPaySelLineParentObject_ID) then
do:
for each bSupplierInvoiceGroups
where bSupplierInvoiceGroups.tiGroupNumber > tSupplierInvoiceGroups.tiGroupNumber and
bSupplierInvoiceGroups.tiPaySelLineParentObject_ID = tSupplierInvoiceGroups.tiPaySelLineParentObject_ID:
bSupplierInvoiceGroups.tiGroupNumber = tSupplierInvoiceGroups.tiGroupNumber.
end.
end.
end.
/* Group Number Desc */
for last tSupplierInvoiceGroups by tSupplierInvoiceGroups.tiGroupNumber:
viMaxGroupNbr = tSupplierInvoiceGroups.tiGroupNumber.
end.
for each tSupplierInvoiceGroups by tSupplierInvoiceGroups.tiPaymentSelectionLineID:
viNewGroupNbr = viMaxGroupNbr - tSupplierInvoiceGroups.tiGroupNumber + 1.
assign tSupplierInvoiceGroups.tiGroupNumber = viNewGroupNbr.
end.