SD Invoice with amount 0 EUR not to be transmitted to FI - oop

I am trying to fix a certain already developed function with the goal that the SD Invoice with amount 0 EUR should not be transmitted to FI. As I understood, the below code is used to select the data from FI and SD:
* select order-related invoices
SELECT * FROM vbfa AS v INTO TABLE gt_vbfa_inv
FOR ALL ENTRIES IN gt_vbak
WHERE vbelv = gt_vbak-vbeln
AND vbtyp_n IN ('M', 'O', 'P', '5', '6')
AND stufe = '00'
AND NOT EXISTS ( SELECT * FROM vbfa
WHERE vbelv = v~vbeln
AND posnv = v~posnn
AND vbtyp_n IN ('N', 'S')
AND stufe = '00' ) .
IF sy-subrc = 0.
* select invoice head status
SELECT DISTINCT * FROM vbuk APPENDING TABLE gt_vbuk_inv
FOR ALL ENTRIES IN gt_vbfa_inv
WHERE vbeln = gt_vbfa_inv-vbeln. "#EC CI_SUBRC
ENDIF.
SORT gt_vbuk_inv BY vbeln.
DELETE ADJACENT DUPLICATES FROM gt_vbuk_inv COMPARING vbeln.
IF me->gv_items = abap_true AND gt_vbuk_inv IS NOT INITIAL.
SELECT * FROM vbrp INTO TABLE gt_vbrp
FOR ALL ENTRIES IN gt_vbuk_inv
WHERE vbeln = gt_vbuk_inv-vbeln. "#EC CI_SUBRC
ENDIF.
As far as I can understand from the above written code, is that the table VBFA is used to get the data for FI, while the table VBRP is used to get the data for SD. What I want to achieve is that when the invoice number does not have a FI document, then the invoice number will be empty.
If the tables BKPF(for the FI) and VBRK(for the SD) would be used, then I could have tried the relation:
vbrk-xblnr=bkpf-xblnr.
However, those tables are not used in the function. May I please ask you, how can I fix the code so that when the invoice number does not have a FI document, thus the invoices with a value of 0 EUR will not generate an FI document, then the invoice number will be empty.
Thank you all in advance!

Since the goal is
the SD Invoice with amount 0 EUR should not be transmitted to FI
I suppose your code is in some user-exit or standard program modification when releasing the SD invoice to Accounting. If so, the BKPF is not created yet and there's no reason in selecting it.
The select from VBFA is not extracting data from FI. Starting from the Sales Order it is extracting the following SD documents (first document flow level only)
M Invoice
N Invoice Cancellation
P Debit Memo
5 Intercompany Invoice
6 Intercompany Credit Memo
And excluding those invoices that have a subsequent cancellation
N Invoice Cancellation
S Credit Memo Cancellation
Those documents can be found in VBRK table (SD invoice header) with the following select
SELECT DISTINCT * FROM vbrk APPENDING TABLE gt_vbrk
FOR ALL ENTRIES IN gt_vbfa_inv
WHERE vbeln = gt_vbfa_inv-vbeln.
Btw: I don't know the reason for the VBUK select since you're not using any document status information
If you're asking for the SD invoices with zero amount with the purpose to not release them to accounting (since otherwise they would produce an error in FI) you don't have to select BKPF but check VBRK-NETWR = 0 for every entry in gt_vbrk table

Related

How to calculate Total transactions amount column with input / output type?

I have two tables : (transactions and Accounts) their columns are as shown in the picture bellow:
the Accounts table is simple just two columns ID and account name.
The important columns in the Transactions table are Amount and type, the type indicates whether the transaction is an input to the account or an output.
I want to find the current total amount (input - output) for each account with SQL.
this what I have tried but I couldn't go further:
select c.TRS_AC_ID, CompAccount, sum(Amount), Type from Accounts c
INNER JOIN Transactions t on c.TRS_AC_ID = t.TRS_AC_ID GROUP by CompAccount, Type
Instead of grouping by the type, you could use a case expression to return "input" transactions as is and "output" transactions as negative numbers:
SELECT c.TRS_AC_ID, CompAccount, SUM(CASE type WHEN 'O' THEN -1 * amount ELSE amount END)
FROM Accounts c
JOIN Transactions t on c.TRS_AC_ID = t.TRS_AC_ID
GROUP BY c.TRS_AC_ID, CompAccount
you can use the following SQL to get the result of input-output, however, if you need individual results then you can use either sub-query as well.
select
(select sum(amount) as input from transaction
where trs_ac_id = '1' and type_io = 'I'))
-
(seelect sum(amount) as output from transaction
where trs_ac_id = '2' and type_io = 'O')) as current_tot_amt
from dual;

Populate rows based on another row ( Copy Prices from branch 0, to all other branches)

I am trying to populate rows based on another row,
For example
Update the Product Price table where branchID = 0
to all other products where the branchid <> 0 based on each product code
In the table there is
7 rows of the same product, each row is meant to be identical, but the only difference is the branchid
I want all data from branch 0 row to populate the rest for the product
my current update script does run, but it uses up so much space on the transaction log that it fails, and it takes 2 hours to run
UPDATE ProductPrice
SET StandardSell = pp2.StandardSell,
StandardBuy = pp2.StandardBuy,
InternalCost = pp2.InternalCost,
BuyPerID = pp2.BuyPerID,
AverageCostPerID = pp2.AverageCostPerID,
InternalCostPerID = pp2.InternalCostPerID,
SellPerID = pp2.SellPerID
FROM (SELECT BranchID, ProductID, StandardSell, StandardBuy,SellPerID, InternalCost,BuyPerID,AverageCostPerID,InternalCostPerID
FROM ProductPrice
WHERE BranchID = 0
) AS pp2 INNER JOIN
ProductPrice AS pp1
on pp1.ProductID = pp2.ProductID
WHERE pp1.ProductID = pp2.ProductID
I want products to be updated with the prices from branch 0 to all other branches per product.
This is too long for a comment.
The first observation is that you should fix your data model. Repeating the same columns on seven records is evidence that your data is not normalized. The seven columns that you want to update should probably be in the ProductPrice table.
Then you want a ProductBranch table, with additional columns and the branch id.
That said, if you are stuck with the data model, you are stuck with an update that basically updates all rows. Instead, create a new table with all the columns you want:
insert into temp_productprice
select . . .
from . . .;
Then truncate productprice and insert the new data into it. A bulk insert is more efficient than a giant update.
Finally, you could also try using window functions:
with toupdate as (
select pp.*,
max(case when branchid = 0 then StandardSell end) as StandardSell_0,
max(case when branchid = 0 then StandardBuy end) as StandardBuy_0,
from productprice pp
. . .
)
update toupdate
set StandardSell = StandardSell_0,
StandardBuy = StandardBuy_0,
. . .
from branchid <> 0;
Thank you for your suggestions,
In the end I just gave the log file more space. Then let it run- it takes 2 hours though lol.
But its done
Thanks the script i posted works for anyone elses use.

Remove Row Data If Qty Zero

I have a data like this in Table Receipts, for the plus value is the amount of receipt of goods while the negative value in case of returns.
In the picture above, the Receiver_No 01267A is the receipt of the first item with Qty_Received 1. Then there is the return of goods on the receipt number of goods 01268A. I want this transaction not to show up.
Here's statement where i have tried.
select I2.Receiver_No,
I2.Purchase_order,
I2.PO_Line,
I2.Qty_received
from (Select Purchase_order,
PO_Line
from Receipts
group by Purchase_order,
PO_Line
having sum(qty_received) <>'0') I1 inner join
Receipts I2 On
I1.Purchase_Order = I2.Purchase_Order and
I1.PO_Line = I2.PO_Line
But the result did not meet with i want.
Please Help.
This will work for the very limited data that you have provided. If you care to provide more information about what the data looks like, then it will be easier to come up with a better solution.
If you have data with a lot of lines that have identical quantities, then this solution will not work.
SELECT
r.Receiver_No, r.Purchase_order, r.PO_Line, r.Qty_received
FROM
receipts r
WHERE
NOT EXISTS (SELECT
purchase_order
FROM
receipts s
WHERE
r.qty_received = -s.qty_received
)
If your requirement is to fetch rows with quantities less than one and not the negative ones :
SELECT * FROM Receipts WHERE ABS(QtyRecvd) >0 AND ABS(QtyRecvd) < 1
Try This
SELECT * FROM Receipts where Qty_received>0 AND Qty_received < 1

SQL Table Joining issue

I have a two tables: "invoice" as I and "Accounts Receivable" as AR.
AR table includes invoice issued (with id 0) and cash received (with id 4), while I table includes invoice amount column and adjustment column.
Apart from regular invoices and adjustments there are cases where adjustments were made to invoice and net affect is 0.00 on AR table. Plus sometimes, invoices are created and written off at invoice table before posting, so AR will have 0.00 amount in AR but I table has $100 in amount and -$100 in adjustment.
I am trying to create a query where it gives me invoice issued and cash received side by side and also create a new column that includes adjustment made for invoices with 0.00 balance in AR. Columns that might help:
AR.ID = unique ID
AR.ARinvnumber= Invoice number from Invoice table
Ar.Type= 0=invoice, 1 = payment received
Ar.Amount= ARamount saved from invoice
I.Id= unique ID
Invoice number = number of invoice
Invamount= Actual invoice amount
Inv Adjustment= Adjustment applied on invoice
Any idea how I can achieve that? I am able to match I and AR table and cash and AR from AR table
Select *
From (select ar.customerId, ar.customername,ar.invnumber ar.amount, i.invamout, i.invadjustment from Ar join I on ar.arinvnumber=i.invoicenumber where ar.artype=1) inv
join
select (select ar.customerId, ar.customername, ar.invnumber ar.amount, i.invamout, i.invadjustment from Ar join I on ar.arinvnumber=i.invoicenumber where ar.artype=1) cash
on inv.invnumber=cash.invnumber and inv.customerid=cash.customerid
after getting this, how can I include those invoices for whom adjustment were made but there was no AR because adjustment equals invoice amount.
Answer:
The following answer worked for me. Basically I wanted to include all the adjustments from invoice table including those ones which are not populated in AR table because the adjustments were made to clear client’s balance related to the work done after final invoice was issues. I used following query
Select *
From (select AR.ARInvnum as ARInvnum, AR.Arclientnumber as Aclient, sum(AR.Amount), I.Invoicenumber, sum(distinct(I.IAmount)), sum(I.IAdjust)
From AR.ARInvnum=I.Invoicenumber
Where ar.artype=0
Group by AR.ARInvnum, I.Invoicenumber, AR.Arclientnumber)AInvoice
Left join
(select AR.ARInvnum as PARInvnum, AR.Arclientnumber as PClient, sum(AR.Amount), I.Invoicenumber, sum (I.IAmount), sum(I.IAdjust)
From AR.ARInvnum=I.Invoicenumber
Where ar.artype=4
Group by AR.ARInvnum, I.Invoicenumber, AR.ARclientnumber)PInvoice
on
AInvoice.ARInvnum=PInvoice.PARInvnum
and
AInvoice.Aclient=PInvoice.PClient
Keep in Mind the Distinct clause in the first portion of the subquery removes any duplicates as well as sum them, so it will look like one summary related to particular invoice number. first portion of the subquery is summarizing based on the invoice issues and the adjustments related to the client. and second part is matching all payments received. I hope, this helps.
You need to include a limiting clause, also known as a where clause. MSDN documentation on select lays out the syntax as follows:
SELECT select_list [ INTO new_table ]
[ FROM table_source ] [ WHERE search_condition ]
[ GROUP BY group_by_expression ]
[ HAVING search_condition ]
[ ORDER BY order_expression [ ASC | DESC ] ]
Be aware, you will not need every expression to create a valid select statement. Also you do not need to join the same query to itself. Why not simplify by running the query by itself?
select
ar.customerId, ar.customername, ar.invnumber,
ar.amount, i.invamout, i.invadjustment
from Ar
join I on ar.arinvnumber=i.invoicenumber
where ar.artype=1
But your questions asks how to limit the results to only
those invoices for whom adjustment were made but there was no [account receivable]
Update your where clause to something like
where ar.artype=1 and i.adjustment is not null and i.adjustment = i.invamount
This will limit the results returned by the select statement to only those records that meet all three of the following criteria:
artype is equal to 1
adjustment is not null
adjustment is equal to invamount
If that result set is too narrow, tweak your where clause. I find it helpful to identify a single record that looks like other records I would like to find. Use that records unique identifier as a test for whether or not your query is working like you expect.

How to design a Select statement with in line functions and single fields

I'm attempting to design a single SELECT statement that will do the following.
I'm creating a report that shows a file number, a statement value associated with the file number, a total invoice value that is built from all of the invoices associated with the file number, and then the difference between the statement and invoice values if there is one. finally it shows the payment due date.
The report is only suppose to show files where there is a difference between the total invoices and the value of the statement. It is also restricted by only invoices that are marked as Payable (not 'V'), by certain charge codes, and by not being 'FLAGGED' as being worked on.
The data is arranged into three tables. IMPSTATP is for the file level and contains the file number and statement value. The other two are the Invoice header and Invoice payable files.
Now obviously what I have below won't work, but I'm running into some difficulties visualizing a single select statement that will.
SELECT
P.OFFIV, FILEST, TOTDST, PDUEST,
sum(P.AMTPIV - P.DTDCIV),
TOTDST - sum(AMTPIV - DTDCIV)
FROM
IMPSTATP
JOIN ACCIHEDP AS H ON FILEST = H.FILEIV and BKRST = H.BKRIV
JOIN ACCIPBLP AS P ON H.INVIV = P.INVIV and H.BKRIV = P.BKRIV and H.OFFIV = P.OFFIV
WHERE
H.VDPDIV <> 'V' AND
(P.CHGPIV = '011' OR
P.CHGPIV = '012' OR
P.CHGPIV = '093') AND
P.VNNMIV <> 'FLAGGED'
GROUP BY FILEST
HAVING
TOTDST - sum(P.AMTPIV - P.DTDCIV) <> 0;
Keep in mind that this is with an old DB2 database on an IBM iSeries. Any and all suggestions would be welcome.