1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940 | *&---------------------------------------------------------------------*
*& 包含 ZSDREPORT_FRM
*&---------------------------------------------------------------------*
*&---------------------------------------------------------------------*
*& Form frm_main
*&---------------------------------------------------------------------*
*& 程序入口
*&---------------------------------------------------------------------*
FORM frm_main .
PERFORM frm_get_auth.
PERFORM frm_get_data.
PERFORM frm_display TABLES gt_data.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form frm_get_auth
*&---------------------------------------------------------------------*
*& 权限相关
*&---------------------------------------------------------------------*
FORM frm_get_auth .
ENDFORM.
*&---------------------------------------------------------------------*
*& Form frm_get_data
*&---------------------------------------------------------------------*
*& 取值相关
*&---------------------------------------------------------------------*
FORM frm_get_data .
" 销售交货查询,以交货单为中心,查询对应销售凭证和开票凭证
IF cb1 = abap_true.
PERFORM frm_get_data_vl.
ENDIF.
" 无交货(服务/借贷项等)发票查询,以销售订单为中心,查询对应发票
IF cb2 = abap_true.
PERFORM frm_get_data_non_vl.
ENDIF.
CHECK gt_data IS NOT INITIAL.
SORT gt_data BY vbeln_va posnr_va
vbeln_vl posnr_vl
vbeln_vf posnr_vf.
DELETE ADJACENT DUPLICATES FROM gt_data COMPARING vbeln_va posnr_va
vbeln_vl posnr_vl
vbeln_vf posnr_vf.
PERFORM frm_fetch_va.
PERFORM frm_fetch_vl.
PERFORM frm_fetch_vf.
PERFORM frm_fetch_vbkd.
PERFORM frm_fetch_vbpa.
PERFORM frm_fetch_amount.
PERFORM frm_fetch_text.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form frm_vl_intersection
*&---------------------------------------------------------------------*
*& 取交集
*&---------------------------------------------------------------------*
FORM frm_intersection
TABLES et_result TYPE tt_sdkey
USING VALUE(it_sdkey1) TYPE tt_sdkey
VALUE(it_sdkey2) TYPE tt_sdkey.
CLEAR et_result[].
CHECK it_sdkey1[] IS NOT INITIAL.
CHECK it_sdkey2[] IS NOT INITIAL.
DATA ls_sdkey TYPE ty_sdkey.
IF lines( it_sdkey1 ) < lines( it_sdkey2 ).
SORT it_sdkey2 BY vbeln posnr.
LOOP AT it_sdkey1 INTO ls_sdkey.
READ TABLE it_sdkey2 TRANSPORTING NO FIELDS WITH KEY
vbeln = ls_sdkey-vbeln
posnr = ls_sdkey-posnr
BINARY SEARCH.
IF sy-subrc = 0.
INSERT ls_sdkey INTO TABLE et_result.
ENDIF.
ENDLOOP.
ELSE.
SORT it_sdkey1 BY vbeln posnr.
LOOP AT it_sdkey2 INTO ls_sdkey.
READ TABLE it_sdkey1 TRANSPORTING NO FIELDS WITH KEY
vbeln = ls_sdkey-vbeln
posnr = ls_sdkey-posnr
BINARY SEARCH.
IF sy-subrc = 0.
INSERT ls_sdkey INTO TABLE et_result.
ENDIF.
ENDLOOP.
ENDIF.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form frm_filter_cancel_billing
*&---------------------------------------------------------------------*
*& 排除冲销和被冲销发票
*&---------------------------------------------------------------------*
FORM frm_filter_cancel_billing CHANGING ct_vf TYPE tt_sfakn.
CHECK ct_vf[] IS NOT INITIAL.
DATA(lt_cancel) = ct_vf[].
SORT lt_cancel BY sfakn.
LOOP AT ct_vf REFERENCE INTO DATA(lr_vf) WHERE sfakn IS INITIAL.
READ TABLE lt_cancel INTO DATA(ls_cancel) WITH KEY sfakn = lr_vf->vbeln_vf BINARY SEARCH.
IF sy-subrc = 0.
lr_vf->sfakn = ls_cancel-vbeln_vf.
ENDIF.
ENDLOOP.
CLEAR lt_cancel.
DELETE ct_vf WHERE sfakn IS NOT INITIAL.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form frm_get_data_vl
*&---------------------------------------------------------------------*
*& 销售交货查询,以交货单为中心,查询对应销售凭证和开票凭证
*&---------------------------------------------------------------------*
FORM frm_get_data_vl .
CLEAR gs_preload.
CLEAR gt_sdkey.
PERFORM frm_preload_vl_from_vl.
PERFORM frm_preload_vl_from_va.
PERFORM frm_preload_vl_from_vf.
IF gs_preload IS NOT INITIAL.
" 预查询
IF gt_sdkey IS NOT INITIAL.
SELECT
vbfa~vbelv AS vbeln_va,
vbfa~posnv AS posnr_va,
vbfa~vbeln AS vbeln_vl,
vbfa~posnn AS posnr_vl
FROM vbfa
JOIN vbak ON vbfa~vbelv = vbak~vbeln
JOIN likp ON vbfa~vbeln = likp~vbeln
FOR ALL ENTRIES IN @gt_sdkey
WHERE vbfa~vbeln = @gt_sdkey-vbeln
AND vbfa~posnn = @gt_sdkey-posnr
INTO TABLE @DATA(lt_vlva).
ENDIF.
ELSE.
" 全量查询
SELECT
vbfa~vbelv AS vbeln_va,
vbfa~posnv AS posnr_va,
vbfa~vbeln AS vbeln_vl,
vbfa~posnn AS posnr_vl
FROM vbfa
JOIN vbak ON vbfa~vbelv = vbak~vbeln
JOIN likp ON vbfa~vbeln = likp~vbeln
INTO TABLE @lt_vlva.
ENDIF.
CHECK lt_vlva IS NOT INITIAL.
" 询报价/合同->销售,需要过滤这部分
SELECT
vbfa~vbelv AS vbeln_other,
vbfa~posnv AS posnr_other,
vbfa~vbeln AS vbeln_va,
vbfa~posnn AS posnr_va
FROM vbfa
JOIN vbak AS other ON vbfa~vbelv = other~vbeln
JOIN vbak AS va ON vbfa~vbeln = va~vbeln
FOR ALL ENTRIES IN @lt_vlva
WHERE vbfa~vbelv = @lt_vlva-vbeln_va
AND vbfa~posnv = @lt_vlva-posnr_va
INTO TABLE @DATA(lt_otherva).
" 交货-发票
IF lt_vlva IS NOT INITIAL.
DATA lt_vlvf TYPE tt_sfakn.
SELECT
vbfa~vbelv AS vbeln_vl,
vbfa~posnv AS posnr_vl,
vbfa~vbeln AS vbeln_vf,
vbfa~posnn AS posnr_vf,
vbrk~sfakn
FROM vbfa
JOIN likp ON vbfa~vbelv = likp~vbeln
JOIN vbrk ON vbfa~vbeln = vbrk~vbeln
FOR ALL ENTRIES IN @lt_vlva
WHERE vbfa~vbelv = @lt_vlva-vbeln_vl
AND vbfa~posnv = @lt_vlva-posnr_vl
INTO CORRESPONDING FIELDS OF TABLE @lt_vlvf.
PERFORM frm_filter_cancel_billing CHANGING lt_vlvf. " 排除冲销和被冲销发票
ENDIF.
" 销售->发票
" 对于退货交货,交货单后续无发票,需要根据销售订单查找
DATA lt_vavf TYPE tt_sfakn.
SELECT
vbfa~vbelv AS vbeln_va,
vbfa~posnv AS posnr_va,
vbfa~vbeln AS vbeln_vf,
vbfa~posnn AS posnr_vf,
vbrk~sfakn " 冲销凭证
FROM vbfa
JOIN vbak ON vbfa~vbelv = vbak~vbeln
JOIN vbrk ON vbfa~vbeln = vbrk~vbeln
FOR ALL ENTRIES IN @lt_vlva
WHERE vbfa~vbelv = @lt_vlva-vbeln_va
AND vbfa~posnv = @lt_vlva-posnr_va
INTO CORRESPONDING FIELDS OF TABLE @lt_vavf.
PERFORM frm_filter_cancel_billing CHANGING lt_vavf. " 排除冲销和被冲销发票
SORT lt_otherva BY vbeln_other posnr_other.
SORT lt_vlvf BY vbeln_vl posnr_vl.
SORT lt_vavf BY vbeln_va posnr_va.
LOOP AT lt_vlva INTO DATA(ls_vlva).
READ TABLE lt_otherva TRANSPORTING NO FIELDS WITH KEY
vbeln_other = ls_vlva-vbeln_va
posnr_other = ls_vlva-posnr_va
BINARY SEARCH.
IF sy-subrc = 0.
CONTINUE.
ENDIF.
DATA ls_data TYPE ty_data.
CLEAR ls_data.
ls_data-vbeln_va = ls_vlva-vbeln_va.
ls_data-posnr_va = ls_vlva-posnr_va.
ls_data-vbeln_vl = ls_vlva-vbeln_vl.
ls_data-posnr_vl = ls_vlva-posnr_vl.
READ TABLE lt_vlvf INTO DATA(ls_vlvf) WITH KEY
vbeln_vl = ls_data-vbeln_vl
posnr_vl = ls_data-posnr_vl
BINARY SEARCH.
IF sy-subrc = 0.
ls_data-vbeln_vf = ls_vlvf-vbeln_vf.
ls_data-posnr_vf = ls_vlvf-posnr_vf.
ELSE.
READ TABLE lt_vavf INTO DATA(ls_vavf) WITH KEY
vbeln_va = ls_data-vbeln_va
posnr_va = ls_data-posnr_va
BINARY SEARCH.
IF sy-subrc = 0.
ls_data-vbeln_vf = ls_vavf-vbeln_vf.
ls_data-posnr_vf = ls_vavf-posnr_vf.
ENDIF.
ENDIF.
INSERT ls_data INTO TABLE gt_data.
ENDLOOP.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form frm_preload_vl_from_vl
*&---------------------------------------------------------------------*
*& 直接按交货单查询
*&---------------------------------------------------------------------*
FORM frm_preload_vl_from_vl .
IF s_vbnvl[] IS NOT INITIAL
OR s_vbtvl[] IS NOT INITIAL
OR s_lfart[] IS NOT INITIAL
OR s_wadat[] IS NOT INITIAL
OR s_matnr[] IS NOT INITIAL
OR s_werks[] IS NOT INITIAL
OR s_lgort[] IS NOT INITIAL
OR s_charg[] IS NOT INITIAL
OR s_wbs[] IS NOT INITIAL
OR s_kunnr[] IS NOT INITIAL
.
SELECT
lips~vbeln,
lips~posnr
FROM likp
JOIN lips ON likp~vbeln = lips~vbeln
LEFT JOIN prps ON lips~ps_psp_pnr = prps~pspnr
WHERE lips~vbeln IN @s_vbnvl
AND likp~vbtyp IN @s_vbtvl
AND likp~lfart IN @s_lfart
AND likp~wadat IN @s_wadat
AND likp~kunnr IN @s_kunnr
AND lips~matnr IN @s_matnr
AND lips~werks IN @s_werks
AND lips~lgort IN @s_lgort
AND lips~charg IN @s_charg
AND prps~posid IN @s_wbs
INTO TABLE @gt_sdkey.
gs_preload-vl = abap_true. " 表示已执行预加载
ENDIF.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form frm_preload_vl_from_va
*&---------------------------------------------------------------------*
*& 根据销售订单查找交货单
*&---------------------------------------------------------------------*
FORM frm_preload_vl_from_va .
IF s_vbnva[] IS NOT INITIAL
OR s_vbtva[] IS NOT INITIAL
OR s_auart[] IS NOT INITIAL
.
DATA lt_sdkey TYPE tt_sdkey.
SELECT
vbfa~vbeln AS vbeln,
vbfa~posnn AS posnr
FROM vbfa
JOIN vbak ON vbfa~vbelv = vbak~vbeln
JOIN likp ON vbfa~vbeln = likp~vbeln
WHERE vbak~vbeln IN @s_vbnva
AND vbak~vbtyp IN @s_vbtva
AND vbak~auart IN @s_auart
INTO TABLE @lt_sdkey.
" 将当前查询结果和之前的查询结果取交集
IF gs_preload IS INITIAL.
gt_sdkey = lt_sdkey.
ELSE.
PERFORM frm_intersection TABLES gt_sdkey USING gt_sdkey lt_sdkey.
ENDIF.
gs_preload-va = abap_true. " 表示已执行预加载
ENDIF.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form frm_preload_vl_from_vf
*&---------------------------------------------------------------------*
*& 根据发票查找交货单
*&---------------------------------------------------------------------*
FORM frm_preload_vl_from_vf .
IF s_vbnvf[] IS NOT INITIAL
OR s_vbtvf[] IS NOT INITIAL
OR s_fkdat[] IS NOT INITIAL
.
DATA lt_sdkey TYPE tt_sdkey.
" 对于发票,先查找发票对应销售单,再根据销售单查找交货单
" 这样一个流程,可以兼容退货的情况(对于退货,交货订单后续是物料凭证)
DATA lt_vavf TYPE tt_sfakn.
SELECT
vbfa~vbelv AS vbeln_va,
vbfa~posnv AS posnr_va,
vbfa~vbeln AS vbeln_vf,
vbfa~posnn AS posnr_vf,
vbrk~sfakn " 冲销凭证
FROM vbfa
JOIN vbak ON vbfa~vbelv = vbak~vbeln
JOIN vbrk ON vbfa~vbeln = vbrk~vbeln
WHERE vbrk~vbeln IN @s_vbnvf
AND vbrk~vbtyp IN @s_vbtvf
AND vbrk~fkdat IN @s_fkdat
INTO CORRESPONDING FIELDS OF TABLE @lt_vavf.
PERFORM frm_filter_cancel_billing CHANGING lt_vavf. " 排除冲销和被冲销发票
IF lt_vavf IS NOT INITIAL.
SELECT
vbfa~vbeln AS vbeln,
vbfa~posnn AS posnr
FROM vbfa
JOIN vbak ON vbfa~vbelv = vbak~vbeln
JOIN likp ON vbfa~vbeln = likp~vbeln
FOR ALL ENTRIES IN @lt_vavf
WHERE vbfa~vbelv = @lt_vavf-vbeln_va
AND vbfa~posnv = @lt_vavf-posnr_va
INTO TABLE @lt_sdkey.
ENDIF.
" 将当前查询结果和之前的查询结果取交集
IF gs_preload IS INITIAL.
gt_sdkey = lt_sdkey.
ELSE.
PERFORM frm_intersection TABLES gt_sdkey USING gt_sdkey lt_sdkey.
ENDIF.
gs_preload-vf = abap_true. " 表示有执行优化
ENDIF.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form frm_get_data_non_vl
*&---------------------------------------------------------------------*
*& 无交货(服务/借贷项等)发票查询,以销售订单为中心,查询对应发票
*&---------------------------------------------------------------------*
FORM frm_get_data_non_vl .
CLEAR gs_preload.
CLEAR gt_sdkey.
PERFORM frm_preload_va_from_va.
PERFORM frm_preload_va_from_vl.
PERFORM frm_preload_va_from_vf.
DATA lt_vavf TYPE tt_sfakn.
IF gs_preload IS NOT INITIAL.
" 预查询
IF gt_sdkey IS NOT INITIAL.
SELECT
vbfa~vbelv AS vbeln_va,
vbfa~posnv AS posnr_va,
vbfa~vbeln AS vbeln_vf,
vbfa~posnn AS posnr_vf,
vbrk~sfakn " 冲销凭证
FROM vbfa
JOIN vbak ON vbfa~vbelv = vbak~vbeln
JOIN vbrk ON vbfa~vbeln = vbrk~vbeln
FOR ALL ENTRIES IN @gt_sdkey
WHERE vbfa~vbelv = @gt_sdkey-vbeln
AND vbfa~posnv = @gt_sdkey-posnr
INTO CORRESPONDING FIELDS OF TABLE @lt_vavf.
ENDIF.
ELSE.
" 全量查询
SELECT
vbfa~vbelv AS vbeln_va,
vbfa~posnv AS posnr_va,
vbfa~vbeln AS vbeln_vf,
vbfa~posnn AS posnr_vf,
vbrk~sfakn " 冲销凭证
FROM vbfa
JOIN vbak ON vbfa~vbelv = vbak~vbeln
JOIN vbrk ON vbfa~vbeln = vbrk~vbeln
INTO CORRESPONDING FIELDS OF TABLE @lt_vavf.
ENDIF.
PERFORM frm_filter_cancel_billing CHANGING lt_vavf. " 排除冲销和被冲销发票
" 无交货判断
IF lt_vavf IS NOT INITIAL.
SELECT
vbfa~vbelv AS vbeln_va,
vbfa~posnv AS posnr_va,
vbfa~vbeln AS vbeln_vl,
vbfa~posnn AS posnr_vl
FROM vbfa
JOIN vbak ON vbfa~vbelv = vbak~vbeln
JOIN likp ON vbfa~vbeln = likp~vbeln
FOR ALL ENTRIES IN @lt_vavf
WHERE vbfa~vbelv = @lt_vavf-vbeln_va
AND vbfa~posnv = @lt_vavf-posnr_va
INTO TABLE @DATA(lt_vavl).
ENDIF.
SORT lt_vavl BY vbeln_va posnr_va.
LOOP AT lt_vavf INTO DATA(ls_vavf).
READ TABLE lt_vavl TRANSPORTING NO FIELDS WITH KEY
vbeln_va = ls_vavf-vbeln_va
posnr_va = ls_vavf-posnr_va
BINARY SEARCH.
IF sy-subrc <> 0.
INSERT CORRESPONDING #( ls_vavf ) INTO TABLE gt_data.
ENDIF.
ENDLOOP.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form frm_preload_vl_from_vl
*&---------------------------------------------------------------------*
*& 直接按交货单查询
*&---------------------------------------------------------------------*
FORM frm_preload_va_from_va.
IF s_vbnva[] IS NOT INITIAL
OR s_vbtva[] IS NOT INITIAL
OR s_auart[] IS NOT INITIAL
OR s_matnr[] IS NOT INITIAL
OR s_werks[] IS NOT INITIAL
OR s_lgort[] IS NOT INITIAL
OR s_charg[] IS NOT INITIAL
OR s_wbs[] IS NOT INITIAL
OR s_vkorg[] IS NOT INITIAL
OR s_vtweg[] IS NOT INITIAL
OR s_spart[] IS NOT INITIAL
OR s_kunnr[] IS NOT INITIAL
.
SELECT
vbap~vbeln,
vbap~posnr
FROM vbak
JOIN vbap ON vbak~vbeln = vbap~vbeln
LEFT JOIN prps ON vbap~ps_psp_pnr = prps~pspnr
WHERE vbak~vbeln IN @s_vbnva
AND vbak~vbtyp IN @s_vbtva
AND vbak~auart IN @s_auart
AND vbak~vkorg IN @s_vkorg
AND vbak~vtweg IN @s_vtweg
AND vbak~kunnr IN @s_kunnr
AND vbap~spart IN @s_spart
AND vbap~matnr IN @s_matnr
AND vbap~werks IN @s_werks
AND vbap~lgort IN @s_lgort
AND vbap~charg IN @s_charg
AND prps~posid IN @s_wbs
INTO TABLE @gt_sdkey.
gs_preload-va = abap_true. " 表示已执行预加载
ENDIF.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form frm_preload_va_from_vl
*&---------------------------------------------------------------------*
*& 不存在这种情况,但假设屏幕有输入交货相关
*&---------------------------------------------------------------------*
FORM frm_preload_va_from_vl .
IF s_vbnvl[] IS NOT INITIAL
OR s_vbtvl[] IS NOT INITIAL
OR s_lfart[] IS NOT INITIAL
.
CLEAR gt_sdkey.
gs_preload-vl = abap_true. " 表示已执行预加载
ENDIF.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form frm_preload_va_from_vf
*&---------------------------------------------------------------------*
*& 根据通过发票找销售订单
*&---------------------------------------------------------------------*
FORM frm_preload_va_from_vf.
IF s_vbnvf[] IS NOT INITIAL
OR s_vbtvf[] IS NOT INITIAL
OR s_fkdat[] IS NOT INITIAL
.
DATA lt_vavf TYPE tt_sfakn.
SELECT
vbfa~vbelv AS vbeln_va,
vbfa~posnv AS posnr_va,
vbfa~vbeln AS vbeln_vf,
vbfa~posnn AS posnr_vf,
vbrk~sfakn " 冲销凭证
FROM vbfa
JOIN vbak ON vbfa~vbelv = vbak~vbeln
JOIN vbrk ON vbfa~vbeln = vbrk~vbeln
WHERE vbrk~vbeln IN @s_vbnvf
AND vbrk~vbtyp IN @s_vbtvf
AND vbrk~fkdat IN @s_fkdat
INTO CORRESPONDING FIELDS OF TABLE @lt_vavf.
PERFORM frm_filter_cancel_billing CHANGING lt_vavf." 排除冲销和被冲销发票
" 无交货判断
IF lt_vavf IS NOT INITIAL.
SELECT
vbfa~vbelv AS vbeln_va,
vbfa~posnv AS posnr_va,
vbfa~vbeln AS vbeln_vl,
vbfa~posnn AS posnr_vl
FROM vbfa
JOIN vbak ON vbfa~vbelv = vbak~vbeln
JOIN likp ON vbfa~vbeln = likp~vbeln
FOR ALL ENTRIES IN @lt_vavf
WHERE vbfa~vbeln = @lt_vavf-vbeln_va
AND vbfa~posnn = @lt_vavf-posnr_va
INTO TABLE @DATA(lt_vavl).
ENDIF.
SORT lt_vavl BY vbeln_va posnr_va.
DATA lt_sdkey TYPE tt_sdkey.
DATA ls_sdkey TYPE ty_sdkey.
LOOP AT lt_vavf INTO DATA(ls_vavf).
READ TABLE lt_vavl TRANSPORTING NO FIELDS WITH KEY
vbeln_va = ls_vavf-vbeln_va
posnr_va = ls_vavf-posnr_va
BINARY SEARCH.
IF sy-subrc <> 0.
CLEAR ls_sdkey.
ls_sdkey-vbeln = ls_vavf-vbeln_va.
ls_sdkey-posnr = ls_vavf-posnr_va.
INSERT ls_sdkey INTO TABLE lt_sdkey.
ENDIF.
ENDLOOP.
" 将当前查询结果和之前的查询结果取交集
IF gs_preload IS INITIAL.
gt_sdkey = lt_sdkey.
ELSE.
PERFORM frm_intersection TABLES gt_sdkey USING gt_sdkey lt_sdkey.
ENDIF.
gs_preload-vf = abap_true. " 表示有执行优化
ENDIF.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form frm_fetch_va
*&---------------------------------------------------------------------*
*& 读取销售信息
*&---------------------------------------------------------------------*
FORM frm_fetch_va .
CHECK gt_data IS NOT INITIAL.
SELECT
vbap~vbeln,
vbap~posnr,
vbak~vbtyp, " 凭证类型
vbak~auart, " 销售订单类型
vbak~vkorg, " 销售组织
vbak~vtweg, " 分销渠道
vbak~spart, " 产品组
vbap~waerk, " 货币
vbap~kzwi1, " 销售小计
vbap~kwmeng, " 订单数量
vbap~zmeng, " 目标数量
vbak~knumv, " 条件号
vbap~meins, " 单位
vbap~matnr, " 物料
vbap~werks, " 工厂
vbap~lgort, " 库存地点
prps~pspnr, " WBS
prps~posid, " WBS
vbap~charg " 批次
FROM vbak
JOIN vbap ON vbak~vbeln = vbap~vbeln
LEFT JOIN prps ON vbap~ps_psp_pnr = prps~pspnr
FOR ALL ENTRIES IN @gt_data
WHERE vbak~vbeln = @gt_data-vbeln_va
INTO TABLE @DATA(lt_va).
SORT lt_va BY vbeln posnr.
LOOP AT gt_data REFERENCE INTO DATA(lr_data).
READ TABLE lt_va INTO DATA(ls_va) WITH KEY
vbeln = lr_data->vbeln_va
posnr = lr_data->posnr_va
BINARY SEARCH.
IF sy-subrc = 0.
lr_data->va = CORRESPONDING #( ls_va ).
lr_data->matnr = ls_va-matnr.
lr_data->werks = ls_va-werks.
lr_data->lgort = ls_va-lgort.
lr_data->pspnr = ls_va-pspnr.
lr_data->posid = ls_va-posid.
lr_data->charg = ls_va-charg.
ENDIF.
ENDLOOP.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form frm_fetch_va
*&---------------------------------------------------------------------*
*& 读取交货单信息
*&---------------------------------------------------------------------*
FORM frm_fetch_vl .
CHECK gt_data IS NOT INITIAL.
SELECT
lips~vbeln, " 交货订单
lips~posnr, " 行项目
likp~vbtyp, " 凭证类型
likp~lfart, " 交货类型
likp~wadat_ist, " 实际交货日期
lips~uecha, " 上层行(判断行项目是否为拆分行)
lips~wbsta, " 处理状态
lips~lfimg, " 交货数量
lips~meins, " 单位
lips~matnr, " 物料
lips~werks, " 工厂
lips~lgort, " 库存地点
prps~pspnr, " WBS
prps~posid, " WBS
lips~charg " 批次
FROM likp
JOIN lips ON likp~vbeln = lips~vbeln
LEFT JOIN prps ON lips~ps_psp_pnr = prps~pspnr
FOR ALL ENTRIES IN @gt_data
WHERE likp~vbeln = @gt_data-vbeln_vl
INTO TABLE @DATA(lt_vl).
SORT lt_vl BY vbeln posnr.
LOOP AT gt_data REFERENCE INTO DATA(lr_data).
READ TABLE lt_vl INTO DATA(ls_vl) WITH KEY
vbeln = lr_data->vbeln_vl
posnr = lr_data->posnr_vl
BINARY SEARCH.
IF sy-subrc = 0.
lr_data->vl = CORRESPONDING #( ls_vl ).
lr_data->matnr = ls_vl-matnr.
lr_data->werks = ls_vl-werks.
lr_data->lgort = ls_vl-lgort.
lr_data->pspnr = ls_vl-pspnr.
lr_data->posid = ls_vl-posid.
lr_data->charg = ls_vl-charg.
ENDIF.
ENDLOOP.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form frm_fetch_vf
*&---------------------------------------------------------------------*
*& 读取发票信息
*&---------------------------------------------------------------------*
FORM frm_fetch_vf .
CHECK gt_data IS NOT INITIAL.
SELECT
vbrp~vbeln, " 发票
vbrp~posnr, " 发票行
vbrk~vbtyp, " 发票凭证类别
vbrk~fkdat, " 开票日期
vbrp~fkimg, " 开票数量
vbrp~meins, " 单位
vbrp~kzwi1, " 发票小计
vbrp~waerk " 货币
FROM vbrk
JOIN vbrp ON vbrk~vbeln = vbrp~vbeln
FOR ALL ENTRIES IN @gt_data
WHERE vbrk~vbeln = @gt_data-vbeln_vf
INTO TABLE @DATA(lt_vf).
SORT lt_vf BY vbeln posnr.
LOOP AT gt_data REFERENCE INTO DATA(lr_data).
READ TABLE lt_vf INTO DATA(ls_vf) WITH KEY
vbeln = lr_data->vbeln_vf
posnr = lr_data->posnr_vf
BINARY SEARCH.
IF sy-subrc = 0.
lr_data->vf = CORRESPONDING #( ls_vf ).
ENDIF.
ENDLOOP.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form frm_fetch_vbkd
*&---------------------------------------------------------------------*
*& 读取VBKD
*&---------------------------------------------------------------------*
FORM frm_fetch_vbkd .
CHECK gt_data IS NOT INITIAL.
SELECT
vbeln,
posnr,
bstkd
FROM vbkd
FOR ALL ENTRIES IN @gt_data
WHERE vbeln = @gt_data-vbeln_va
INTO TABLE @DATA(lt_vbkd).
SORT lt_vbkd BY vbeln posnr.
LOOP AT gt_data REFERENCE INTO DATA(lr_data).
READ TABLE lt_vbkd INTO DATA(ls_vbkd) WITH KEY
vbeln = lr_data->vbeln_va
BINARY SEARCH.
IF sy-subrc = 0.
lr_data->bstkd_va = ls_vbkd-bstkd.
ENDIF.
ENDLOOP.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form frm_fetch_vbpa
*&---------------------------------------------------------------------*
*& 销售业务货币
*&---------------------------------------------------------------------*
FORM frm_fetch_vbpa .
CHECK gt_data IS NOT INITIAL.
SELECT
vbeln,
parvw,
kunnr
FROM vbpa
FOR ALL ENTRIES IN @gt_data
WHERE vbeln = @gt_data-vbeln_va
AND posnr = '' " 取抬头业务伙伴
INTO TABLE @DATA(lt_vbpa).
SORT lt_vbpa BY vbeln parvw.
LOOP AT gt_data REFERENCE INTO DATA(lr_data).
" 重复代码
DATA ls_vbpa LIKE LINE OF lt_vbpa.
DEFINE _get_partner.
CLEAR ls_vbpa.
READ TABLE lt_vbpa INTO ls_vbpa WITH KEY
vbeln = lr_data->vbeln_va
parvw = &1
BINARY SEARCH.
IF sy-subrc = 0.
&2 = ls_vbpa-kunnr.
ENDIF.
END-OF-DEFINITION.
_get_partner 'AG' lr_data->kunag.
_get_partner 'RE' lr_data->kunre.
_get_partner 'RG' lr_data->kunrg.
ENDLOOP.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form frm_fetch_amount
*&---------------------------------------------------------------------*
*& 数量与金额处理
*&---------------------------------------------------------------------*
FORM frm_fetch_amount .
CHECK gt_data IS NOT INITIAL.
SELECT
knumv,
kposn,
stunr,
zaehk,
kschl,
waers,
kbetr,
kpein
FROM prcd_elements
FOR ALL ENTRIES IN @gt_data
WHERE knumv = @gt_data-knumv_va
AND kinak = '' " 排除未激活的定价
INTO TABLE @DATA(lt_prcd_elements).
" 对于多个价格,取最新的
SORT lt_prcd_elements BY knumv kposn kschl
zaehk DESCENDING .
DELETE ADJACENT DUPLICATES FROM lt_prcd_elements COMPARING knumv kposn kschl.
" 对于下面类型,数量金额按负数处理
DATA lt_vbtyp_neg_opt TYPE RANGE OF vbtyp.
lt_vbtyp_neg_opt = VALUE #( sign = 'I' option = 'EQ'
( low = 'H' ) " 退货
( low = 'T' ) " 订单的退货交货
( low = 'K' ) " 贷项凭证申请
( low = 'O' ) " 贷项凭证
).
LOOP AT gt_data REFERENCE INTO DATA(lr_data).
" 重复代码
DATA ls_prcd_elements LIKE LINE OF lt_prcd_elements.
DEFINE _get_prcd_elements.
READ TABLE lt_prcd_elements INTO ls_prcd_elements WITH KEY
knumv = lr_data->knumv_va
kposn = lr_data->posnr_va
kschl = &1
BINARY SEARCH.
IF sy-subrc <> 0.
CLEAR ls_prcd_elements.
ENDIF.
END-OF-DEFINITION.
" 判断是否为退货之类
IF lr_data->vbtyp_va IN lt_vbtyp_neg_opt
OR lr_data->vbtyp_vl IN lt_vbtyp_neg_opt
OR lr_data->vbtyp_vf IN lt_vbtyp_neg_opt.
lr_data->zfactor = -1.
ELSE.
lr_data->zfactor = 1.
ENDIF.
" 数量金额方向校准
lr_data->kwmeng_va *= lr_data->zfactor.
lr_data->zmeng_va *= lr_data->zfactor.
lr_data->kzwi1_va *= lr_data->zfactor.
lr_data->lfimg_vl *= lr_data->zfactor.
lr_data->fkimg_vf *= lr_data->zfactor.
lr_data->kzwi1_vf *= lr_data->zfactor.
" 税率
_get_prcd_elements 'MWSI'.
lr_data->ztax_rate = ls_prcd_elements-kbetr / 100. " 底表记录13,转换为0.13
" 销售数量,对于订单,取订单数量,对于和同或服务框架之类的,取目标数量
IF lr_data->kwmeng_va <> 0.
lr_data->zquan2 = lr_data->kwmeng_va.
ELSEIF lr_data->zmeng_va <> 0.
lr_data->zquan2 = lr_data->zmeng_va.
ENDIF.
" 销售单价 = 数量(订单数量或目标数量) / 小计
" 看项目实际需求,可能会取定价值,这边简单取小计值即可
IF lr_data->zquan2 <> 0.
lr_data->zamount1 = lr_data->kzwi1_va / lr_data->zquan2.
ENDIF.
" 销售含税总金额 = 小计
lr_data->zamount3 = lr_data->kzwi1_va.
IF lr_data->vbeln_vl IS NOT INITIAL.
lr_data->zamount4 = lr_data->zamount1. " 交货单价 = 销售单价
" 根据行项目过账状态判断交货数量,不会有中间状态
IF lr_data->wbsta_vl = 'C'. " 完全交货
lr_data->zquan5 = lr_data->lfimg_vl. " 交货数量
ENDIF.
lr_data->zamount6 = lr_data->zquan5 * lr_data->zamount4. " 交货含税总金额 = 交货数量 * 交货单价
lr_data->zquan7 = lr_data->zquan2 - lr_data->zquan5. " 未交货数量 = 销售数量 - 交货数量
lr_data->zamount8 = lr_data->zquan7 * lr_data->zamount4. " 未交货含税总金额 = 未交货数量 * 交货单价
ENDIF.
" 开票单价 = 数量 / 小计
IF lr_data->fkimg_vf <> 0.
lr_data->zamount9 = lr_data->kzwi1_vf / lr_data->fkimg_vf.
ENDIF.
lr_data->zquan10 = lr_data->lfimg_vl. " 开票数量
lr_data->zamount11 = lr_data->zquan10 * lr_data->zamount9. " 开票含税总金额 = 开票数量 * 开票单价
IF lr_data->vbeln_vl IS NOT INITIAL.
lr_data->zquan12 = lr_data->zquan5 - lr_data->lfimg_vl. " 未开票数量 = 交货数量 - 开票数量
ELSE.
lr_data->zquan12 = lr_data->zquan2 - lr_data->lfimg_vl. " 未开票数量 = 销售数量 - 开票数量
ENDIF.
lr_data->zamount13 = lr_data->zquan12 * lr_data->zamount11. " 未交货含税总金额 = 未交货数量 * 交货单价
ENDLOOP.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form frm_fetch_text
*&---------------------------------------------------------------------*
*& 读取文本
*&---------------------------------------------------------------------*
FORM frm_fetch_text .
CHECK gt_data IS NOT INITIAL.
* LOOP AT gt_data REFERENCE INTO DATA(lr_data).
* lr_data->kunag_text = zcl_text=>auto( lr_data->kunag ).
* lr_data->kunnr_text = zcl_text=>auto( lr_data->kunnr ).
* lr_data->kunre_text = zcl_text=>auto( lr_data->kunre ).
* lr_data->kunrg_text = zcl_text=>auto( lr_data->kunrg ).
* lr_data->maktx = zcl_text=>auto( lr_data->matnr ).
* ENDLOOP.
ENDFORM.
|