|
@@ -1,1444 +1,1341 @@
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
+package com.yonge.cooleshow.portal.service.impl;
|
|
|
+
|
|
|
+import cn.hutool.core.bean.BeanUtil;
|
|
|
+import cn.hutool.core.collection.CollUtil;
|
|
|
+import cn.hutool.core.map.MapUtil;
|
|
|
+import com.alibaba.fastjson.JSON;
|
|
|
+import com.github.pagehelper.PageHelper;
|
|
|
+import com.ym.mec.common.entity.HttpResponseResult;
|
|
|
+import com.ym.mec.common.entity.MallCreateOrderModel;
|
|
|
+import com.ym.mec.common.entity.OrderCancelModel;
|
|
|
+import com.ym.mec.common.entity.RefundModel;
|
|
|
+import com.ym.mec.common.exception.BizException;
|
|
|
+import com.ym.mec.common.service.IdGeneratorService;
|
|
|
+import com.ym.mec.thirdparty.adapay.entity.BaseResult;
|
|
|
+import com.ym.mec.web.WebFeignService;
|
|
|
+import com.yonge.cooleshow.mall.common.api.CommonPage;
|
|
|
+import com.yonge.cooleshow.mall.common.enums.OrderCacheEnum;
|
|
|
+import com.yonge.cooleshow.mall.common.enums.TradeStatusEnum;
|
|
|
+import com.yonge.cooleshow.mall.common.exception.Asserts;
|
|
|
+import com.yonge.cooleshow.mall.common.service.RedisService;
|
|
|
+import com.yonge.cooleshow.mall.common.util.DistributedLock;
|
|
|
+import com.yonge.cooleshow.mall.common.util.StringUtil;
|
|
|
+import com.yonge.cooleshow.mbg.mapper.*;
|
|
|
+import com.yonge.cooleshow.mbg.model.*;
|
|
|
+import com.yonge.cooleshow.portal.dao.PortalOrderDao;
|
|
|
+import com.yonge.cooleshow.portal.dao.PortalOrderItemDao;
|
|
|
+import com.yonge.cooleshow.portal.dao.PortalProductDao;
|
|
|
+import com.yonge.cooleshow.portal.domain.*;
|
|
|
+import com.yonge.cooleshow.portal.service.*;
|
|
|
+import org.redisson.api.RedissonClient;
|
|
|
+import org.slf4j.Logger;
|
|
|
+import org.slf4j.LoggerFactory;
|
|
|
+import org.springframework.beans.factory.annotation.Autowired;
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
+import org.springframework.transaction.annotation.Transactional;
|
|
|
+import org.springframework.util.CollectionUtils;
|
|
|
+
|
|
|
+import java.math.BigDecimal;
|
|
|
+import java.math.RoundingMode;
|
|
|
+import java.time.LocalDateTime;
|
|
|
+import java.time.ZoneId;
|
|
|
+import java.util.*;
|
|
|
+import java.util.concurrent.TimeUnit;
|
|
|
+import java.util.stream.Collectors;
|
|
|
+
|
|
|
+
|
|
|
+ * 前台订单管理Service
|
|
|
+ * Created by macro on 2018/8/30.
|
|
|
+ */
|
|
|
+@Service
|
|
|
+public class OmsPortalOrderServiceImpl implements OmsPortalOrderService {
|
|
|
+
|
|
|
+ private static final Logger LOG = LoggerFactory.getLogger(OmsPortalOrderServiceImpl.class);
|
|
|
+ @Autowired
|
|
|
+ private UmsMemberService memberService;
|
|
|
+ @Autowired
|
|
|
+ private OmsCartItemService cartItemService;
|
|
|
+ @Autowired
|
|
|
+ private UmsMemberReceiveAddressService memberReceiveAddressService;
|
|
|
+ @Autowired
|
|
|
+ private UmsMemberCouponService memberCouponService;
|
|
|
+ @Autowired
|
|
|
+ private UmsIntegrationConsumeSettingMapper integrationConsumeSettingMapper;
|
|
|
+ @Autowired
|
|
|
+ private PmsSkuStockMapper skuStockMapper;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private OmsOrderMapper orderMapper;
|
|
|
+ @Autowired
|
|
|
+ private PortalOrderItemDao orderItemDao;
|
|
|
+ @Autowired
|
|
|
+ private SmsCouponHistoryMapper couponHistoryMapper;
|
|
|
+ @Autowired
|
|
|
+ private RedisService redisService;
|
|
|
+ private String REDIS_KEY_ORDER_ID = "redis.key.orderId";
|
|
|
+ private String REDIS_DATABASE = "redis.database";
|
|
|
+ @Autowired
|
|
|
+ private PortalOrderDao portalOrderDao;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private UserOrderRefundMapper userOrderRefundMapper;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private IdGeneratorService idGeneratorService;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private WebFeignService webFeignService;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private OmsOrderSettingMapper orderSettingMapper;
|
|
|
+ @Autowired
|
|
|
+ private OmsOrderItemMapper orderItemMapper;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private PmsProductMapper pmsProductMapper;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private RedissonClient redissonClient;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private UserOrderPaymentService userOrderPaymentService;
|
|
|
+
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private PortalProductDao productDao;
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public ConfirmOrderResult generateConfirmOrder(List<Long> cartIds) {
|
|
|
+ ConfirmOrderResult result = new ConfirmOrderResult();
|
|
|
+
|
|
|
+ UmsMember currentMember = memberService.getCurrentMember();
|
|
|
+ List<CartPromotionItem> cartPromotionItemList = cartItemService.listPromotion(currentMember.getId(), cartIds,
|
|
|
+ true);
|
|
|
+ result.setCartPromotionItemList(cartPromotionItemList);
|
|
|
+
|
|
|
+ List<UmsMemberReceiveAddress> memberReceiveAddressList = memberReceiveAddressService.list();
|
|
|
+ result.setMemberReceiveAddressList(memberReceiveAddressList);
|
|
|
+
|
|
|
+ List<SmsCouponHistoryDetail> couponHistoryDetailList = memberCouponService.listCart(cartPromotionItemList, 1);
|
|
|
+ result.setCouponHistoryDetailList(couponHistoryDetailList);
|
|
|
+
|
|
|
+ result.setMemberIntegration(currentMember.getIntegration());
|
|
|
+
|
|
|
+ UmsIntegrationConsumeSetting integrationConsumeSetting = integrationConsumeSettingMapper.selectByPrimaryKey(1L);
|
|
|
+ result.setIntegrationConsumeSetting(integrationConsumeSetting);
|
|
|
+
|
|
|
+ ConfirmOrderResult.CalcAmount calcAmount = calcCartAmount(cartPromotionItemList);
|
|
|
+ result.setCalcAmount(calcAmount);
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public Map<String, Object> generateOrder(OrderParam orderParam) {
|
|
|
+ OmsOrder order = new OmsOrder();
|
|
|
+ String orderSn = generateOrderSn();
|
|
|
+ if (!StringUtil.isEmpty(orderParam.getOrderNo())) {
|
|
|
+
|
|
|
+ OmsOrderDetail detail = detail(orderParam.getOrderNo());
|
|
|
+ if (detail != null && detail.getStatus() == 0) {
|
|
|
+
|
|
|
+ UserOrderPayment userOrderPayment = userOrderPaymentService.getByOrderNoAndStatusPaying(
|
|
|
+ orderParam.getOrderNo());
|
|
|
+ userOrderPayment.setStatus(TradeStatusEnum.close.getCode());
|
|
|
+
|
|
|
+ String oldOrderNo = userOrderPayment.getAdapayNo();
|
|
|
+ userOrderPaymentService.saveOrUpdate(userOrderPayment);
|
|
|
+
|
|
|
+
|
|
|
+ userOrderPayment.setStatus(TradeStatusEnum.pending.getCode());
|
|
|
+ userOrderPayment.setAdapayNo(orderSn);
|
|
|
+ userOrderPayment.setId(null);
|
|
|
+ userOrderPaymentService.saveOrUpdate(userOrderPayment);
|
|
|
+
|
|
|
+ return feignMecCreateOrder(order.getCouponId(), oldOrderNo, orderSn, null, detail.getMemberId().intValue(), detail.getTotalAmount(),
|
|
|
+ JSON.toJSONString(detail));
|
|
|
+ } else {
|
|
|
+ throw new BizException("订单信息获取失败");
|
|
|
+ }
|
|
|
+
|
|
|
+ } else {
|
|
|
+ if (orderParam.getMemberReceiveAddressId() == null) {
|
|
|
+ throw new BizException("请选择收货地址");
|
|
|
+ }
|
|
|
+ if (orderParam.getOrderAmount() == null) {
|
|
|
+ throw new BizException("订单金额校验不通过");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ List<OmsOrderItem> orderItemList = new ArrayList<>();
|
|
|
+
|
|
|
+ UmsMember currentMember;
|
|
|
+ if (orderParam.getUserId() != null && orderParam.getUserId() > 0) {
|
|
|
+ currentMember = memberService.getById(orderParam.getUserId());
|
|
|
+ } else {
|
|
|
+ currentMember = memberService.getCurrentMember();
|
|
|
+ }
|
|
|
+
|
|
|
+ List<CartPromotionItem> cartPromotionItemList = cartItemService.listPromotion(currentMember.getId(),
|
|
|
+ orderParam.getCartIds(), true);
|
|
|
+ for (CartPromotionItem cartPromotionItem : cartPromotionItemList) {
|
|
|
+
|
|
|
+ OmsOrderItem orderItem = new OmsOrderItem();
|
|
|
+ orderItem.setProductId(cartPromotionItem.getProductId());
|
|
|
+ orderItem.setProductName(cartPromotionItem.getProductName());
|
|
|
+ orderItem.setProductPic(cartPromotionItem.getProductPic());
|
|
|
+ orderItem.setProductAttr(cartPromotionItem.getProductAttr());
|
|
|
+ orderItem.setProductBrand(cartPromotionItem.getProductBrand());
|
|
|
+ orderItem.setProductSn(cartPromotionItem.getProductSn());
|
|
|
+ orderItem.setProductPrice(cartPromotionItem.getPrice());
|
|
|
+ orderItem.setProductQuantity(cartPromotionItem.getQuantity());
|
|
|
+ orderItem.setProductSkuId(cartPromotionItem.getProductSkuId());
|
|
|
+ orderItem.setProductSkuCode(cartPromotionItem.getProductSkuCode());
|
|
|
+ orderItem.setProductCategoryId(cartPromotionItem.getProductCategoryId());
|
|
|
+ orderItem.setPromotionAmount(cartPromotionItem.getReduceAmount());
|
|
|
+ orderItem.setPromotionName(cartPromotionItem.getPromotionMessage());
|
|
|
+ orderItem.setGiftIntegration(cartPromotionItem.getIntegration());
|
|
|
+ orderItem.setGiftGrowth(cartPromotionItem.getGrowth());
|
|
|
+ orderItem.setPromoterId(cartPromotionItem.getPromoterId());
|
|
|
+ orderItem.setPrecisionAmount(BigDecimal.ZERO);
|
|
|
+ orderItemList.add(orderItem);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!hasStock(cartPromotionItemList)) {
|
|
|
+ Asserts.fail("库存不足,无法下单");
|
|
|
+ }
|
|
|
+
|
|
|
+ BigDecimal amount = calcTotalAmount(orderItemList);
|
|
|
+ Map data = feignMecCouponAmount(orderParam.getCouponId(), orderParam.getOrderAmount());
|
|
|
+
|
|
|
+ BigDecimal couponAmount = MapUtil.get(data, "mallCouponAmount", BigDecimal.class);
|
|
|
+ if (couponAmount == null) {
|
|
|
+ couponAmount = BigDecimal.ZERO;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (StringUtil.isEmpty(orderParam.getCouponId())) {
|
|
|
+
|
|
|
+ for (OmsOrderItem orderItem : orderItemList) {
|
|
|
+ orderItem.setCouponAmount(new BigDecimal(0));
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ if (couponAmount.compareTo(orderParam.getOrderAmount()) > 0) {
|
|
|
+ couponAmount = orderParam.getOrderAmount();
|
|
|
+ }
|
|
|
+ handleCouponAmount(orderItemList, couponAmount);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (orderParam.getUseIntegration() == null || orderParam.getUseIntegration().equals(0)) {
|
|
|
+
|
|
|
+ for (OmsOrderItem orderItem : orderItemList) {
|
|
|
+ orderItem.setIntegrationAmount(new BigDecimal(0));
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+
|
|
|
+ BigDecimal totalAmount = calcTotalAmount(orderItemList);
|
|
|
+ BigDecimal integrationAmount = getUseIntegrationAmount(orderParam.getUseIntegration(), totalAmount,
|
|
|
+ currentMember, orderParam.getCouponId() != null);
|
|
|
+ if (integrationAmount.compareTo(new BigDecimal(0)) == 0) {
|
|
|
+ Asserts.fail("积分不可用");
|
|
|
+ } else {
|
|
|
+
|
|
|
+ for (OmsOrderItem orderItem : orderItemList) {
|
|
|
+ BigDecimal perAmount = orderItem.getProductPrice()
|
|
|
+ .divide(totalAmount, 3, RoundingMode.HALF_EVEN)
|
|
|
+ .multiply(integrationAmount);
|
|
|
+ orderItem.setIntegrationAmount(perAmount);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ handleRealAmount(orderItemList);
|
|
|
+
|
|
|
+ lockSkuStock(cartPromotionItemList);
|
|
|
+
|
|
|
+
|
|
|
+ lockProductStock(cartPromotionItemList);
|
|
|
+
|
|
|
+
|
|
|
+ String cartIds = orderParam.getCartIds().stream().map(String::valueOf).collect(Collectors.joining());
|
|
|
+ order.setCartIds(cartIds);
|
|
|
+ order.setDiscountAmount(new BigDecimal(0));
|
|
|
+ order.setTotalAmount(amount);
|
|
|
+ order.setFreightAmount(new BigDecimal(0));
|
|
|
+ order.setPromotionAmount(calcPromotionAmount(orderItemList));
|
|
|
+ order.setPromotionInfo(getOrderPromotionInfo(orderItemList));
|
|
|
+ order.setPlatformType(orderParam.getPlatformType() == null?"STUDENT":orderParam.getPlatformType());
|
|
|
+ if (StringUtil.isEmpty(orderParam.getCouponId())) {
|
|
|
+ order.setCouponAmount(new BigDecimal(0));
|
|
|
+ } else {
|
|
|
+ order.setCouponId(orderParam.getCouponId());
|
|
|
+ order.setCouponAmount(couponAmount);
|
|
|
+ }
|
|
|
+ if (orderParam.getUseIntegration() == null) {
|
|
|
+ order.setIntegration(0);
|
|
|
+ order.setIntegrationAmount(new BigDecimal(0));
|
|
|
+ } else {
|
|
|
+ order.setIntegration(orderParam.getUseIntegration());
|
|
|
+ order.setIntegrationAmount(calcIntegrationAmount(orderItemList));
|
|
|
+ }
|
|
|
+ LOG.info("payAmount:{},totalAmount:{},couponAmount:{}",order.getTotalAmount().subtract(couponAmount),order.getTotalAmount(),couponAmount);
|
|
|
+ if (orderParam.getOrderAmount().compareTo(order.getTotalAmount().subtract(couponAmount)) != 0) {
|
|
|
+ throw new BizException("订单金额校验不通过");
|
|
|
+ }
|
|
|
+ order.setPayAmount(orderParam.getOrderAmount());
|
|
|
+
|
|
|
+ order.setMemberId(currentMember.getId());
|
|
|
+ order.setCreateTime(new Date());
|
|
|
+ order.setMemberUsername(currentMember.getUsername());
|
|
|
+
|
|
|
+ order.setPayType(orderParam.getPayType());
|
|
|
+
|
|
|
+ order.setSourceType(1);
|
|
|
+
|
|
|
+ order.setStatus(0);
|
|
|
+
|
|
|
+ order.setOrderType(0);
|
|
|
+
|
|
|
+ UmsMemberReceiveAddress address = memberReceiveAddressService.getItem(orderParam.getMemberReceiveAddressId());
|
|
|
+ order.setReceiverName(address.getName());
|
|
|
+ order.setReceiverPhone(address.getPhoneNumber());
|
|
|
+ order.setReceiverPostCode(address.getPostCode());
|
|
|
+ order.setReceiverProvince(address.getProvince());
|
|
|
+ order.setReceiverCity(address.getCity());
|
|
|
+ order.setReceiverRegion(address.getRegion());
|
|
|
+ order.setReceiverDetailAddress(address.getDetailAddress());
|
|
|
+
|
|
|
+ order.setConfirmStatus(0);
|
|
|
+ order.setDeleteStatus(0);
|
|
|
+
|
|
|
+ order.setIntegration(calcGifIntegration(orderItemList));
|
|
|
+
|
|
|
+ order.setGrowth(calcGiftGrowth(orderItemList));
|
|
|
+
|
|
|
+ order.setOrderSn(orderSn);
|
|
|
+
|
|
|
+ List<OmsOrderSetting> orderSettings = orderSettingMapper.selectByExample(new OmsOrderSettingExample());
|
|
|
+ if (CollUtil.isNotEmpty(orderSettings)) {
|
|
|
+ order.setAutoConfirmDay(orderSettings.get(0).getConfirmOvertime());
|
|
|
+ }
|
|
|
+
|
|
|
+ orderMapper.insert(order);
|
|
|
+ for (OmsOrderItem orderItem : orderItemList) {
|
|
|
+ orderItem.setOrderId(order.getId());
|
|
|
+ orderItem.setOrderSn(order.getOrderSn());
|
|
|
+ }
|
|
|
+ orderItemDao.insertList(orderItemList);
|
|
|
+
|
|
|
+ if (orderParam.getCouponId() != null) {
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ if (orderParam.getUseIntegration() != null) {
|
|
|
+ order.setUseIntegration(orderParam.getUseIntegration());
|
|
|
+ memberService.updateIntegration(currentMember.getId(),
|
|
|
+ currentMember.getIntegration() - orderParam.getUseIntegration());
|
|
|
+ }
|
|
|
+
|
|
|
+ deleteCartItemList(cartPromotionItemList, currentMember);
|
|
|
+
|
|
|
+ sendDelayMessageCancelOrder(order.getId());
|
|
|
+ Map<String, Object> result = new HashMap<>();
|
|
|
+ result.put("order", order);
|
|
|
+ result.put("orderItemList", orderItemList);
|
|
|
+ result.put("orderType","paying");
|
|
|
+
|
|
|
+
|
|
|
+ UserOrderPayment userOrderPayment = new UserOrderPayment();
|
|
|
+ userOrderPayment.setOpenType("ADAPAY");
|
|
|
+ userOrderPayment.setPaymentClient(orderParam.getPlatformType());
|
|
|
+ userOrderPayment.setOrderNo(order.getOrderSn());
|
|
|
+ userOrderPayment.setAdapayNo(order.getOrderSn());
|
|
|
+ userOrderPayment.setStatus(TradeStatusEnum.pending.getCode());
|
|
|
+
|
|
|
+ if (order.getPayAmount().compareTo(BigDecimal.ZERO) == 0) {
|
|
|
+ paySuccess(order.getId(),order.getPayType());
|
|
|
+ order.setStatus(1);
|
|
|
+ result.put("orderType","success");
|
|
|
+ userOrderPayment.setStatus(TradeStatusEnum.succeeded.getCode());
|
|
|
+ }
|
|
|
+ userOrderPaymentService.save(userOrderPayment);
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ OmsOrderDetail detail = detail(order.getOrderSn());
|
|
|
+ data = feignMecCreateOrder(orderParam.getCouponId(),orderParam.getOrderNo(), orderSn,
|
|
|
+ orderParam.getTeacherId()==null?null:orderParam.getTeacherId().intValue(),
|
|
|
+ currentMember.getId().intValue(), amount,JSON.toJSONString(detail));
|
|
|
+ result.put("pay",data);
|
|
|
+
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+ private Map feignMecCouponAmount(String couponId,BigDecimal amount) {
|
|
|
+
|
|
|
+ MallCreateOrderModel model = new MallCreateOrderModel();
|
|
|
+ model.setCouponIdList(StringUtil.toIntegerList(couponId));
|
|
|
+ model.setAmount(amount);
|
|
|
+ HttpResponseResult<Map> mapHttpResponseResult = webFeignService.couponAmount(model);
|
|
|
+ if (!mapHttpResponseResult.getStatus()) {
|
|
|
+ throw new BizException("管乐迷获取优惠券优惠失败");
|
|
|
+ }
|
|
|
+ return mapHttpResponseResult.getData();
|
|
|
+ }
|
|
|
+
|
|
|
+ private Map feignMecCreateOrder(String couponId, String oldOrderNo, String orderSn, Integer teacherId, Integer userId, BigDecimal amount, String orderDetail) {
|
|
|
+
|
|
|
+ MallCreateOrderModel model = new MallCreateOrderModel();
|
|
|
+ model.setAmount(amount);
|
|
|
+ model.setOrderNo(orderSn);
|
|
|
+ if (!userId.equals(teacherId)) {
|
|
|
+ model.setTeacherId(teacherId);
|
|
|
+ }
|
|
|
+ model.setUserId(userId);
|
|
|
+ model.setCouponIdList(StringUtil.toIntegerList(couponId));
|
|
|
+ model.setOldOrderNo(oldOrderNo);
|
|
|
+ model.setOrderInfo(orderDetail);
|
|
|
+ HttpResponseResult<Map> mapHttpResponseResult = webFeignService.mallCreateOrder(model);
|
|
|
+ if (!mapHttpResponseResult.getStatus()) {
|
|
|
+ throw new BizException("管乐迷订单生成失败");
|
|
|
+ }
|
|
|
+ Map data = mapHttpResponseResult.getData();
|
|
|
+ if (Integer.valueOf(0).equals(MapUtil.get(data,"mallStatus",Integer.class))) {
|
|
|
+ throw new BizException("管乐迷订单生成失败");
|
|
|
+ }
|
|
|
+ return data;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public Integer paySuccess(Long orderId, Integer payType) {
|
|
|
+
|
|
|
+ OmsOrder order = new OmsOrder();
|
|
|
+ order.setId(orderId);
|
|
|
+ order.setStatus(1);
|
|
|
+ order.setPaymentTime(new Date());
|
|
|
+ order.setPayType(payType);
|
|
|
+ orderMapper.updateByPrimaryKeySelective(order);
|
|
|
+
|
|
|
+ OmsOrderDetail orderDetail = portalOrderDao.getDetail(orderId);
|
|
|
+
|
|
|
+ int count = portalOrderDao.updateSkuStock(orderDetail.getOrderItemList());
|
|
|
+
|
|
|
+
|
|
|
+ updateProductStock(orderDetail);
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ return count;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ * 减商品库存
|
|
|
+ */
|
|
|
+ private void updateProductStock(OmsOrderDetail orderDetail) {
|
|
|
+ Map<Long, List<OmsOrderItem>> collect = orderDetail.getOrderItemList()
|
|
|
+ .stream()
|
|
|
+ .collect(Collectors.groupingBy(OmsOrderItem::getProductId));
|
|
|
+
|
|
|
+ List<ProductStock> productStockList = new ArrayList<>();
|
|
|
+ for (Map.Entry<Long, List<OmsOrderItem>> entry : collect.entrySet()) {
|
|
|
+ ProductStock stock = new ProductStock();
|
|
|
+ stock.setProductId(entry.getKey());
|
|
|
+ List<OmsOrderItem> value = entry.getValue();
|
|
|
+ if (CollectionUtils.isEmpty(value)) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ int sum = value.stream().mapToInt(OmsOrderItem::getProductQuantity).sum();
|
|
|
+ stock.setStock(sum);
|
|
|
+ productStockList.add(stock);
|
|
|
+ }
|
|
|
+ productDao.updateProductStock(productStockList);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public Integer cancelTimeOutOrder() {
|
|
|
+ Integer count = 0;
|
|
|
+ OmsOrderSetting orderSetting = orderSettingMapper.selectByPrimaryKey(1L);
|
|
|
+
|
|
|
+ List<OmsOrderDetail> timeOutOrders = portalOrderDao.getTimeOutOrders(orderSetting.getNormalOrderOvertime(),
|
|
|
+ orderSetting.getPayOrderOvertime());
|
|
|
+ if (CollectionUtils.isEmpty(timeOutOrders)) {
|
|
|
+ return count;
|
|
|
+ }
|
|
|
+ for (OmsOrderDetail timeOutOrder : timeOutOrders) {
|
|
|
+
|
|
|
+ DistributedLock.of(redissonClient)
|
|
|
+ .runIfLockCanGet(OrderCacheEnum.LOCK_ORDER_NO_MALL.getRedisKey(timeOutOrder.getOrderSn())
|
|
|
+ , () -> {
|
|
|
+ if (timeOutOrder.getStatus() == 0 || timeOutOrder.getStatus() == 6) {
|
|
|
+ try {
|
|
|
+ cancelOrder(timeOutOrder.getId(), "超时取消");
|
|
|
+ } catch (Exception e) {
|
|
|
+ LOG.warn("订单取消失败,{}",e.fillInStackTrace());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }, 60L, TimeUnit.SECONDS);
|
|
|
+
|
|
|
+ }
|
|
|
+ return timeOutOrders.size();
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void cancelOrder(Long orderId, String message) {
|
|
|
+
|
|
|
+ OmsOrderExample example = new OmsOrderExample();
|
|
|
+ example.createCriteria().andIdEqualTo(orderId).andDeleteStatusEqualTo(0);
|
|
|
+ List<OmsOrder> cancelOrderList = orderMapper.selectByExample(example);
|
|
|
+ if (CollectionUtils.isEmpty(cancelOrderList)) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ OmsOrder cancelOrder = cancelOrderList.get(0);
|
|
|
+ if (cancelOrder != null && (cancelOrder.getStatus() == 0 || cancelOrder.getStatus() == 6)) {
|
|
|
+ UserOrderPayment userOrderPayment = userOrderPaymentService.getByOrderNoAndStatusPaying(
|
|
|
+ cancelOrder.getOrderSn());
|
|
|
+ if (userOrderPayment != null) {
|
|
|
+ HttpResponseResult<OrderCancelModel> responseResult = webFeignService.cancelOrder(userOrderPayment.getAdapayNo());
|
|
|
+ if (!responseResult.getStatus()) {
|
|
|
+ throw new BizException("远程取消失败");
|
|
|
+ }
|
|
|
+ OrderCancelModel data = responseResult.getData();
|
|
|
+ if (!data.getSuccess()) {
|
|
|
+ throw new BizException("远程取消失败");
|
|
|
+ }
|
|
|
+ if (data.getStatus()) {
|
|
|
+ LOG.info("订单支付成功,修改订单状态");
|
|
|
+ orderSuccess(cancelOrder, cancelOrder.getPayAmount(), data.getPayChannel());
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ cancelOrder.setStatus(4);
|
|
|
+ orderMapper.updateByPrimaryKeySelective(cancelOrder);
|
|
|
+ OmsOrderItemExample orderItemExample = new OmsOrderItemExample();
|
|
|
+ orderItemExample.createCriteria().andOrderIdEqualTo(orderId);
|
|
|
+ List<OmsOrderItem> orderItemList = orderItemMapper.selectByExample(orderItemExample);
|
|
|
+
|
|
|
+ if (!CollectionUtils.isEmpty(orderItemList)) {
|
|
|
+ portalOrderDao.releaseSkuStockLock(orderItemList);
|
|
|
+ portalOrderDao.releaseProductStockLock(orderItemList);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ if (cancelOrder.getUseIntegration() != null) {
|
|
|
+ UmsMember member = memberService.getById(cancelOrder.getMemberId());
|
|
|
+ memberService.updateIntegration(cancelOrder.getMemberId(),
|
|
|
+ member.getIntegration() + cancelOrder.getUseIntegration());
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ } else {
|
|
|
+ throw new BizException("订单状态非待支付和支付中,不能取消");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void sendDelayMessageCancelOrder(Long orderId) {
|
|
|
+
|
|
|
+ OmsOrderSetting orderSetting = orderSettingMapper.selectByPrimaryKey(1L);
|
|
|
+ long delayTimes = orderSetting.getNormalOrderOvertime() * 60 * 1000L;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void confirmReceiveOrder(Long orderId) {
|
|
|
+
|
|
|
+ OmsOrder order = orderMapper.selectByPrimaryKey(orderId);
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ if (order.getStatus() != 2) {
|
|
|
+ Asserts.fail("该订单还未发货!");
|
|
|
+ }else if (order.getStatus() == 3) {
|
|
|
+ Asserts.fail("已确认收货!");
|
|
|
+ }
|
|
|
+ order.setStatus(3);
|
|
|
+ order.setConfirmStatus(1);
|
|
|
+ order.setReceiveTime(new Date());
|
|
|
+ orderMapper.updateByPrimaryKey(order);
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public CommonPage<OmsOrderDetail> list(String status, Integer pageNum, Integer pageSize) {
|
|
|
+ if (status.equals("-1")) {
|
|
|
+ status = null;
|
|
|
+ }
|
|
|
+ UmsMember member = memberService.getCurrentMember();
|
|
|
+ PageHelper.startPage(pageNum, pageSize);
|
|
|
+ OmsOrderExample orderExample = new OmsOrderExample();
|
|
|
+ OmsOrderExample.Criteria criteria = orderExample.createCriteria();
|
|
|
+ criteria.andDeleteStatusEqualTo(0).andMemberIdEqualTo(member.getId());
|
|
|
+ if (status != null && !StringUtil.isEmpty(status)) {
|
|
|
+ List<Long> list = StringUtil.toLongList(status);
|
|
|
+ List<Integer> collect = list.stream().map(Long::intValue).collect(Collectors.toList());
|
|
|
+ criteria.andStatusIn(collect);
|
|
|
+ }
|
|
|
+ orderExample.setOrderByClause(" field(status,'0','6','1','2','3','4','5'),create_time desc");
|
|
|
+ List<OmsOrder> orderList = orderMapper.selectByExample(orderExample);
|
|
|
+ CommonPage<OmsOrder> orderPage = CommonPage.restPage(orderList);
|
|
|
+
|
|
|
+ CommonPage<OmsOrderDetail> resultPage = new CommonPage<>();
|
|
|
+ resultPage.setPageNum(orderPage.getPageNum());
|
|
|
+ resultPage.setPageSize(orderPage.getPageSize());
|
|
|
+ resultPage.setTotal(orderPage.getTotal());
|
|
|
+ resultPage.setTotalPage(orderPage.getTotalPage());
|
|
|
+ if (CollUtil.isEmpty(orderList)) {
|
|
|
+ return resultPage;
|
|
|
+ }
|
|
|
+
|
|
|
+ List<Long> orderIds = orderList.stream().map(OmsOrder::getId).collect(Collectors.toList());
|
|
|
+ OmsOrderItemExample orderItemExample = new OmsOrderItemExample();
|
|
|
+ orderItemExample.createCriteria().andOrderIdIn(orderIds);
|
|
|
+ List<OmsOrderItem> orderItemList = orderItemMapper.selectByExample(orderItemExample);
|
|
|
+ List<OmsOrderDetail> orderDetailList = new ArrayList<>();
|
|
|
+ for (OmsOrder omsOrder : orderList) {
|
|
|
+ OmsOrderDetail orderDetail = new OmsOrderDetail();
|
|
|
+ BeanUtil.copyProperties(omsOrder, orderDetail);
|
|
|
+ List<OmsOrderItem> relatedItemList = orderItemList.stream()
|
|
|
+ .filter(item -> item.getOrderId()
|
|
|
+ .equals(orderDetail.getId()))
|
|
|
+ .collect(Collectors.toList());
|
|
|
+ orderDetail.setOrderItemList(relatedItemList);
|
|
|
+ orderDetailList.add(orderDetail);
|
|
|
+ }
|
|
|
+ resultPage.setList(orderDetailList);
|
|
|
+ return resultPage;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public OmsOrderDetail detail(Long orderId) {
|
|
|
+ OmsOrder omsOrder = orderMapper.selectByPrimaryKey(orderId);
|
|
|
+ OmsOrderItemExample example = new OmsOrderItemExample();
|
|
|
+ example.createCriteria().andOrderIdEqualTo(orderId);
|
|
|
+ List<OmsOrderItem> orderItemList = orderItemMapper.selectByExample(example);
|
|
|
+ OmsOrderDetail orderDetail = new OmsOrderDetail();
|
|
|
+ BeanUtil.copyProperties(omsOrder, orderDetail);
|
|
|
+ orderDetail.setOrderItemList(orderItemList);
|
|
|
+ return orderDetail;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public OmsOrderDetail detail(String orderSn) {
|
|
|
+ OmsOrderExample orderExample = new OmsOrderExample();
|
|
|
+ orderExample.createCriteria().andOrderSnEqualTo(orderSn);
|
|
|
+ List<OmsOrder> omsOrders = orderMapper.selectByExample(orderExample);
|
|
|
+ if (CollUtil.isEmpty(omsOrders)) {
|
|
|
+ throw new BizException("订单信息错误");
|
|
|
+ } else if (omsOrders.size() != 1) {
|
|
|
+ throw new BizException("订单号重复");
|
|
|
+ }
|
|
|
+ OmsOrder omsOrder = omsOrders.get(0);
|
|
|
+ OmsOrderItemExample example = new OmsOrderItemExample();
|
|
|
+ example.createCriteria().andOrderIdEqualTo(omsOrder.getId());
|
|
|
+ List<OmsOrderItem> orderItemList = orderItemMapper.selectByExample(example);
|
|
|
+ OmsOrderDetail orderDetail = new OmsOrderDetail();
|
|
|
+ BeanUtil.copyProperties(omsOrder, orderDetail);
|
|
|
+ orderDetail.setOrderItemList(orderItemList);
|
|
|
+ return orderDetail;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void deleteOrder(Long orderId) {
|
|
|
+ UmsMember member = memberService.getCurrentMember();
|
|
|
+ OmsOrder order = orderMapper.selectByPrimaryKey(orderId);
|
|
|
+ if (!member.getId().equals(order.getMemberId())) {
|
|
|
+ Asserts.fail("不能删除他人订单!");
|
|
|
+ }
|
|
|
+ if (order.getStatus() == 3 || order.getStatus() == 4) {
|
|
|
+ order.setDeleteStatus(1);
|
|
|
+ orderMapper.updateByPrimaryKey(order);
|
|
|
+ } else {
|
|
|
+ Asserts.fail("只能删除已完成或已关闭的订单!");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public OmsOrder getOrderById(Long orderId) {
|
|
|
+ return orderMapper.selectByPrimaryKey(orderId);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public Integer autoReceive() {
|
|
|
+ OmsOrderSetting omsOrderSetting = orderSettingMapper.selectByPrimaryKey(1L);
|
|
|
+ Integer confirmOvertime = omsOrderSetting.getConfirmOvertime();
|
|
|
+ LocalDateTime localDateTime = LocalDateTime.now().plusDays(-confirmOvertime);
|
|
|
+ OmsOrderExample orderExample = new OmsOrderExample();
|
|
|
+ orderExample.createCriteria().andStatusEqualTo(2).andDeleteStatusEqualTo(0).andConfirmStatusEqualTo(0)
|
|
|
+ .andDeliveryTimeLessThanOrEqualTo(Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant()));
|
|
|
+
|
|
|
+ List<OmsOrder> omsOrders = orderMapper.selectByExample(orderExample);
|
|
|
+ if (CollectionUtils.isEmpty(omsOrders)) {
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+ for (OmsOrder omsOrder : omsOrders) {
|
|
|
+
|
|
|
+ DistributedLock.of(redissonClient)
|
|
|
+ .runIfLockCanGet(OrderCacheEnum.LOCK_ORDER_NO_MALL.getRedisKey(omsOrder.getOrderSn())
|
|
|
+ , () -> {
|
|
|
+ try {
|
|
|
+ this.confirmReceiveOrder(omsOrder.getId());
|
|
|
+
|
|
|
+ }catch (Exception e) {
|
|
|
+ LOG.warn("订单收货,{}",e.fillInStackTrace());
|
|
|
+ }
|
|
|
+ }, 60L, TimeUnit.SECONDS);
|
|
|
+ }
|
|
|
+ return omsOrders.size();
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public Integer shareProfit() {
|
|
|
+ OmsOrderSetting omsOrderSetting = orderSettingMapper.selectByPrimaryKey(1L);
|
|
|
+ Integer finishOvertime = omsOrderSetting.getFinishOvertime();
|
|
|
+ LocalDateTime localDateTime = LocalDateTime.now().plusDays(-finishOvertime);
|
|
|
+ OmsOrderExample orderExample = new OmsOrderExample();
|
|
|
+ orderExample.createCriteria().andStatusEqualTo(3).andDeleteStatusEqualTo(0).andConfirmStatusEqualTo(1)
|
|
|
+ .andAfterSaleEqualTo(0)
|
|
|
+ .andReceiverCityIsNotNull()
|
|
|
+ .andReceiveTimeLessThan(Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant()));
|
|
|
+
|
|
|
+ List<OmsOrder> omsOrders = orderMapper.selectByExample(orderExample);
|
|
|
+ if (CollectionUtils.isEmpty(omsOrders)) {
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+ for (OmsOrder omsOrder : omsOrders) {
|
|
|
+
|
|
|
+ DistributedLock.of(redissonClient)
|
|
|
+ .runIfLockCanGet(OrderCacheEnum.LOCK_ORDER_NO_MALL.getRedisKey(omsOrder.getOrderSn())
|
|
|
+ , () -> {
|
|
|
+ try {
|
|
|
+ this.FinishReceiveOrder(omsOrder.getId());
|
|
|
+
|
|
|
+ } catch (Exception e) {
|
|
|
+ LOG.warn("停止售后失败,{}",e.fillInStackTrace());
|
|
|
+ }
|
|
|
+ }, 60L, TimeUnit.SECONDS);
|
|
|
+ }
|
|
|
+ return omsOrders.size();
|
|
|
+ }
|
|
|
+
|
|
|
+ private void FinishReceiveOrder(Long orderId) {
|
|
|
+
|
|
|
+
|
|
|
+ OmsOrder order = orderMapper.selectByPrimaryKey(orderId);
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ if (order.getStatus() != 3) {
|
|
|
+ Asserts.fail("未确认收货!");
|
|
|
+ }
|
|
|
+ order.setAfterSale(1);
|
|
|
+ orderMapper.updateByPrimaryKey(order);
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ * 处理回调-支付成功
|
|
|
+ * @author liweifan
|
|
|
+ * @param: hfRes
|
|
|
+ * @updateTime 2022/4/27 15:09
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ @Transactional
|
|
|
+ public void paymentSucceededHandle(String orderNo, BigDecimal payAmount, String payChannel) {
|
|
|
+
|
|
|
+ UserOrderPayment orderPayment = userOrderPaymentService.getByAdapayNo(orderNo);
|
|
|
+ if (orderPayment == null) {
|
|
|
+ throw new BizException("订单支付信息未找到");
|
|
|
+ }
|
|
|
+ OmsOrderDetail detail = detail(orderPayment.getOrderNo());
|
|
|
+ if (detail.getStatus() == 0) {
|
|
|
+ orderSuccess(detail, payAmount, payChannel);
|
|
|
+
|
|
|
+ orderPayment.setStatus(TradeStatusEnum.succeeded.getCode());
|
|
|
+ userOrderPaymentService.saveOrUpdate(orderPayment);
|
|
|
+ Map<String,Object> notifyMap = new HashMap<>();
|
|
|
+ notifyMap.put("channelType", payChannel);
|
|
|
+ notifyMap.put("tradeState", "1");
|
|
|
+ notifyMap.put("totalMoney", payAmount);
|
|
|
+ notifyMap.put("merOrderNo",orderNo);
|
|
|
+ HttpResponseResult httpResponseResult = webFeignService.updateOrder(notifyMap);
|
|
|
+ if (!httpResponseResult.getStatus()) {
|
|
|
+ throw new BizException(httpResponseResult.getMsg());
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ LOG.error("汇付支付回调,订单状态异常。 req is {}", detail.getOrderSn());
|
|
|
+
|
|
|
+
|
|
|
+ orderRefund(orderPayment,detail.getPayAmount().toString());
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ * 支付成功,业务退款
|
|
|
+ */
|
|
|
+ private void orderRefund(UserOrderPayment userOrderPayment,String refundAmount) {
|
|
|
+ UserOrderRefund userOrderRefund = userOrderRefundMapper.selectByPayOrderNo(userOrderPayment.getAdapayNo());
|
|
|
+ if (userOrderRefund != null && userOrderRefund.getStatus().equals("succeeded")) {
|
|
|
+ LOG.warn("支付金额已退回");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ String orderSn = generateOrderSn();
|
|
|
+
|
|
|
+ HttpResponseResult<Map<String,String>> httpResponseResult = webFeignService.getBaseUrl(userOrderPayment.getAdapayNo());
|
|
|
+ if (!httpResponseResult.getStatus()) {
|
|
|
+ throw new BizException("获取回调路径失败");
|
|
|
+ }
|
|
|
+ Map<String, String> data = httpResponseResult.getData();
|
|
|
+ String baseUrl = MapUtil.getStr(data,"baseUrl");
|
|
|
+ String transNo = MapUtil.getStr(data,"transNo");
|
|
|
+
|
|
|
+ RefundModel refundModel = new RefundModel();
|
|
|
+ refundModel.setRefundNo(orderSn);
|
|
|
+ refundModel.setOrderNo(userOrderPayment.getAdapayNo());
|
|
|
+ refundModel.setNotifyUrl(baseUrl + "/api-mall-portal/payment/callback");
|
|
|
+ HttpResponseResult<BaseResult<Map<String, Object>>> refund = webFeignService.refund(refundModel);
|
|
|
+ if (!refund.getStatus()) {
|
|
|
+ LOG.error("退款失败:{}",refund.getMsg());
|
|
|
+ throw new BizException("退款失败");
|
|
|
+ }
|
|
|
+ BaseResult<Map<String, Object>> mapBaseResult = refund.getData();
|
|
|
+ userOrderRefund = new UserOrderRefund();
|
|
|
+ userOrderRefund.setOrderNo(orderSn);
|
|
|
+ userOrderRefund.setPayTransNo(transNo);
|
|
|
+ userOrderRefund.setRefundAmt(new BigDecimal(refundAmount));
|
|
|
+ userOrderRefund.setPayOrderNo(userOrderPayment.getOrderNo());
|
|
|
+ if (mapBaseResult.getStatus()) {
|
|
|
+ Map<String,Object> refundBill = mapBaseResult.getData();
|
|
|
+ userOrderRefund.setRefundAmt(new BigDecimal(MapUtil.getStr(refundBill,"reversed_amt")));
|
|
|
+ userOrderRefund.setStatus(TradeStatusEnum.pending.getCode());
|
|
|
+ } else {
|
|
|
+ userOrderRefund.setStatus(TradeStatusEnum.failed.getCode());
|
|
|
+ userOrderRefund.setPayFailMsg("退款失败:" +mapBaseResult.getMsg());
|
|
|
+ }
|
|
|
+ userOrderRefundMapper.insert(userOrderRefund);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ * 处理回调-支付失败
|
|
|
+ * @author liweifan
|
|
|
+ * @param: hfRes
|
|
|
+ * @updateTime 2022/4/27 15:09
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ @Transactional
|
|
|
+ public void paymentFailedHandle(String orderNo, Map<String, Object> notifyMap) {
|
|
|
+ UserOrderPayment orderPayment = userOrderPaymentService.getByAdapayNo(orderNo);
|
|
|
+ if (orderPayment == null) {
|
|
|
+ throw new BizException("订单支付信息未找到");
|
|
|
+ }
|
|
|
+ OmsOrderDetail detail = detail(orderPayment.getOrderNo());
|
|
|
+ if (null == detail) {
|
|
|
+ LOG.error("汇付支付回调,订单未找到。 req is {}", orderNo);
|
|
|
+ throw new BizException("订单未找到");
|
|
|
+ }
|
|
|
+ if (detail.getStatus() == 0) {
|
|
|
+ cancelOrder(detail.getId(), "支付失败");
|
|
|
+
|
|
|
+
|
|
|
+ orderPayment.setStatus(TradeStatusEnum.failed.getCode());
|
|
|
+ userOrderPaymentService.saveOrUpdate(orderPayment);
|
|
|
+ HttpResponseResult httpResponseResult = webFeignService.updateOrder(notifyMap);
|
|
|
+ if (!httpResponseResult.getStatus()) {
|
|
|
+ throw new BizException(httpResponseResult.getMsg());
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ LOG.error("汇付支付回调,订单状态异常。 req is {}", orderNo);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public List<OmsOrderDetail> list(List<String> adapayNoList) {
|
|
|
+ String adapayNos = adapayNoList.stream().collect(Collectors.joining(","));
|
|
|
+
|
|
|
+ List<OmsOrder> orderList = portalOrderDao.listByAdapayNo(adapayNoList,adapayNos);
|
|
|
+
|
|
|
+ List<Long> orderIds = orderList.stream().map(OmsOrder::getId).collect(Collectors.toList());
|
|
|
+ OmsOrderItemExample orderItemExample = new OmsOrderItemExample();
|
|
|
+ orderItemExample.createCriteria().andOrderIdIn(orderIds);
|
|
|
+ List<OmsOrderItem> orderItemList = orderItemMapper.selectByExample(orderItemExample);
|
|
|
+ List<OmsOrderDetail> orderDetailList = new ArrayList<>();
|
|
|
+ for (OmsOrder omsOrder : orderList) {
|
|
|
+ OmsOrderDetail orderDetail = new OmsOrderDetail();
|
|
|
+ BeanUtil.copyProperties(omsOrder, orderDetail);
|
|
|
+ List<OmsOrderItem> relatedItemList = orderItemList.stream()
|
|
|
+ .filter(item -> item.getOrderId()
|
|
|
+ .equals(orderDetail.getId()))
|
|
|
+ .collect(Collectors.toList());
|
|
|
+ orderDetail.setOrderItemList(relatedItemList);
|
|
|
+ orderDetailList.add(orderDetail);
|
|
|
+ }
|
|
|
+ return orderDetailList;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ * 订单完成
|
|
|
+ *
|
|
|
+ * @param: detail
|
|
|
+ * @updateTime 2022/4/13 17:17
|
|
|
+ */
|
|
|
+ @Transactional(rollbackFor = Exception.class)
|
|
|
+ public void orderSuccess(OmsOrder detail,BigDecimal payAmount,String payChannel) {
|
|
|
+
|
|
|
+ if (payAmount.compareTo(detail.getPayAmount()) != 0) {
|
|
|
+ LOG.error("订单金额和实际支付金额不符");
|
|
|
+ throw new BizException("订单金额和实际支付金额不符");
|
|
|
+ } else {
|
|
|
+ if ("alipay_qr".equals(payChannel) || "alipay_wap".equals(payChannel)) {
|
|
|
+ paySuccess(detail.getId(), 1);
|
|
|
+ } else if ("wx_pub".equals(payChannel) || "wx_app".equals(payChannel)) {
|
|
|
+ paySuccess(detail.getId(), 2);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ * 退款成功
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ @Transactional
|
|
|
+ public void paymentRefundSucceededHandle(String payTransNo, String refundAmount, String refundTransNo, String feeAmt) {
|
|
|
+
|
|
|
+ LOG.info("refund payTransNo is {}", payTransNo);
|
|
|
+ if (payTransNo == null) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ UserOrderRefund userOrderRefund = userOrderRefundMapper.selectByPayTansNo(payTransNo);
|
|
|
+ if (userOrderRefund == null) {
|
|
|
+ LOG.warn("未找到退款订单");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ userOrderRefund.setArrivalTime(new Date());
|
|
|
+ userOrderRefund.setStatus(TradeStatusEnum.succeeded.getCode());
|
|
|
+ userOrderRefund.setTransNo(refundTransNo);
|
|
|
+ userOrderRefund.setFeeAmt(new BigDecimal(feeAmt));
|
|
|
+ userOrderRefund.setRefundAmt(new BigDecimal(refundAmount));
|
|
|
+
|
|
|
+ userOrderRefundMapper.updateByPrimaryKeySelective(userOrderRefund);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ * 退款失败
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ @Transactional
|
|
|
+ public void paymentRefundFailedHandle(String payTransNo, String msg, String refundTransNo) {
|
|
|
+ if (payTransNo == null) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ UserOrderRefund userOrderRefund = userOrderRefundMapper.selectByPayTansNo(payTransNo);
|
|
|
+ userOrderRefund.setArrivalTime(new Date());
|
|
|
+ userOrderRefund.setStatus(TradeStatusEnum.failed.getCode());
|
|
|
+ userOrderRefund.setPayFailMsg(msg);
|
|
|
+ userOrderRefund.setTransNo(refundTransNo);
|
|
|
+
|
|
|
+ userOrderRefundMapper.updateByPrimaryKeySelective(userOrderRefund);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ * 生成18位订单编号:8位日期+2位平台号码+2位支付方式+6位以上自增id
|
|
|
+ */
|
|
|
+ private String generateOrderSn() {
|
|
|
+ return String.valueOf(idGeneratorService.generatorId("mall"));
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ * 删除下单商品的购物车信息
|
|
|
+ */
|
|
|
+ private void deleteCartItemList(List<CartPromotionItem> cartPromotionItemList, UmsMember currentMember) {
|
|
|
+ List<Long> ids = new ArrayList<>();
|
|
|
+ for (CartPromotionItem cartPromotionItem : cartPromotionItemList) {
|
|
|
+ ids.add(cartPromotionItem.getId());
|
|
|
+ }
|
|
|
+ cartItemService.delete(currentMember.getId(), ids);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ * 计算该订单赠送的成长值
|
|
|
+ */
|
|
|
+ private Integer calcGiftGrowth(List<OmsOrderItem> orderItemList) {
|
|
|
+ int sum = 0;
|
|
|
+ for (OmsOrderItem orderItem : orderItemList) {
|
|
|
+ sum = sum + orderItem.getGiftGrowth() * orderItem.getProductQuantity();
|
|
|
+ }
|
|
|
+ return sum;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ * 计算该订单赠送的积分
|
|
|
+ */
|
|
|
+ private Integer calcGifIntegration(List<OmsOrderItem> orderItemList) {
|
|
|
+ int sum = 0;
|
|
|
+ for (OmsOrderItem orderItem : orderItemList) {
|
|
|
+ sum += orderItem.getGiftIntegration() * orderItem.getProductQuantity();
|
|
|
+ }
|
|
|
+ return sum;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ * 将优惠券信息更改为指定状态
|
|
|
+ *
|
|
|
+ * @param couponId 优惠券id
|
|
|
+ * @param memberId 会员id
|
|
|
+ * @param useStatus 0->未使用;1->已使用
|
|
|
+ */
|
|
|
+ private void updateCouponStatus(Long couponId, Long memberId, Integer useStatus) {
|
|
|
+ if (couponId == null) return;
|
|
|
+
|
|
|
+ SmsCouponHistoryExample example = new SmsCouponHistoryExample();
|
|
|
+ example.createCriteria()
|
|
|
+ .andMemberIdEqualTo(memberId)
|
|
|
+ .andCouponIdEqualTo(couponId)
|
|
|
+ .andUseStatusEqualTo(useStatus == 0 ? 1 : 0);
|
|
|
+ List<SmsCouponHistory> couponHistoryList = couponHistoryMapper.selectByExample(example);
|
|
|
+ if (!CollectionUtils.isEmpty(couponHistoryList)) {
|
|
|
+ SmsCouponHistory couponHistory = couponHistoryList.get(0);
|
|
|
+ couponHistory.setUseTime(new Date());
|
|
|
+ couponHistory.setUseStatus(useStatus);
|
|
|
+ couponHistoryMapper.updateByPrimaryKeySelective(couponHistory);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private void handleRealAmount(List<OmsOrderItem> orderItemList) {
|
|
|
+ for (OmsOrderItem orderItem : orderItemList) {
|
|
|
+
|
|
|
+ BigDecimal realAmount = orderItem.getProductPrice()
|
|
|
+ .subtract(orderItem.getPromotionAmount())
|
|
|
+ .subtract(orderItem.getCouponAmount())
|
|
|
+ .subtract(orderItem.getIntegrationAmount());
|
|
|
+ orderItem.setRealAmount(realAmount);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ * 获取订单促销信息
|
|
|
+ */
|
|
|
+ private String getOrderPromotionInfo(List<OmsOrderItem> orderItemList) {
|
|
|
+ StringBuilder sb = new StringBuilder();
|
|
|
+ for (OmsOrderItem orderItem : orderItemList) {
|
|
|
+ sb.append(orderItem.getPromotionName());
|
|
|
+ sb.append(";");
|
|
|
+ }
|
|
|
+ String result = sb.toString();
|
|
|
+ if (result.endsWith(";")) {
|
|
|
+ result = result.substring(0, result.length() - 1);
|
|
|
+ }
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ * 计算订单应付金额
|
|
|
+ */
|
|
|
+ private BigDecimal calcPayAmount(OmsOrder order) {
|
|
|
+
|
|
|
+ return order.getTotalAmount()
|
|
|
+ .add(order.getFreightAmount())
|
|
|
+ .subtract(order.getPromotionAmount())
|
|
|
+ .subtract(order.getCouponAmount())
|
|
|
+ .subtract(order.getIntegrationAmount());
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ * 计算订单优惠券金额
|
|
|
+ */
|
|
|
+ private BigDecimal calcIntegrationAmount(List<OmsOrderItem> orderItemList) {
|
|
|
+ BigDecimal integrationAmount = new BigDecimal(0);
|
|
|
+ for (OmsOrderItem orderItem : orderItemList) {
|
|
|
+ if (orderItem.getIntegrationAmount() != null) {
|
|
|
+ integrationAmount = integrationAmount.add(
|
|
|
+ orderItem.getIntegrationAmount().multiply(new BigDecimal(orderItem.getProductQuantity())));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return integrationAmount;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ * 计算订单优惠券金额
|
|
|
+ */
|
|
|
+ private BigDecimal calcCouponAmount(List<OmsOrderItem> orderItemList) {
|
|
|
+ BigDecimal couponAmount = new BigDecimal(0);
|
|
|
+ for (OmsOrderItem orderItem : orderItemList) {
|
|
|
+ if (orderItem.getCouponAmount() != null) {
|
|
|
+ couponAmount = couponAmount.add(
|
|
|
+ orderItem.getCouponAmount().multiply(new BigDecimal(orderItem.getProductQuantity())));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return couponAmount;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ * 计算订单活动优惠
|
|
|
+ */
|
|
|
+ private BigDecimal calcPromotionAmount(List<OmsOrderItem> orderItemList) {
|
|
|
+ BigDecimal promotionAmount = new BigDecimal(0);
|
|
|
+ for (OmsOrderItem orderItem : orderItemList) {
|
|
|
+ if (orderItem.getPromotionAmount() != null) {
|
|
|
+ promotionAmount = promotionAmount.add(
|
|
|
+ orderItem.getPromotionAmount().multiply(new BigDecimal(orderItem.getProductQuantity())));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return promotionAmount;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ * 获取可用积分抵扣金额
|
|
|
+ *
|
|
|
+ * @param useIntegration 使用的积分数量
|
|
|
+ * @param totalAmount 订单总金额
|
|
|
+ * @param currentMember 使用的用户
|
|
|
+ * @param hasCoupon 是否已经使用优惠券
|
|
|
+ */
|
|
|
+ private BigDecimal getUseIntegrationAmount(Integer useIntegration, BigDecimal totalAmount, UmsMember currentMember, boolean hasCoupon) {
|
|
|
+ BigDecimal zeroAmount = new BigDecimal(0);
|
|
|
+
|
|
|
+ if (useIntegration.compareTo(currentMember.getIntegration()) > 0) {
|
|
|
+ return zeroAmount;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ UmsIntegrationConsumeSetting integrationConsumeSetting = integrationConsumeSettingMapper.selectByPrimaryKey(1L);
|
|
|
+ if (hasCoupon && integrationConsumeSetting.getCouponStatus().equals(0)) {
|
|
|
+
|
|
|
+ return zeroAmount;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (useIntegration.compareTo(integrationConsumeSetting.getUseUnit()) < 0) {
|
|
|
+ return zeroAmount;
|
|
|
+ }
|
|
|
+
|
|
|
+ BigDecimal integrationAmount = new BigDecimal(useIntegration).divide(
|
|
|
+ new BigDecimal(integrationConsumeSetting.getUseUnit()), 2, RoundingMode.HALF_EVEN);
|
|
|
+ BigDecimal maxPercent = new BigDecimal(integrationConsumeSetting.getMaxPercentPerOrder()).divide(
|
|
|
+ new BigDecimal(100), 2, RoundingMode.HALF_EVEN);
|
|
|
+ if (integrationAmount.compareTo(totalAmount.multiply(maxPercent)) > 0) {
|
|
|
+ return zeroAmount;
|
|
|
+ }
|
|
|
+ return integrationAmount;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ * 对优惠券优惠进行处理
|
|
|
+ *
|
|
|
+ * @param orderItemList order_item列表
|
|
|
+ * @param couponAmount 可用优惠券详情
|
|
|
+ */
|
|
|
+ private void handleCouponAmount(List<OmsOrderItem> orderItemList, BigDecimal couponAmount) {
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ calcPerCouponAmount(orderItemList, couponAmount);
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ * 对每个下单商品进行优惠券金额分摊的计算
|
|
|
+ *
|
|
|
+ * @param orderItemList 可用优惠券的下单商品商品
|
|
|
+ */
|
|
|
+ private void calcPerCouponAmount(List<OmsOrderItem> orderItemList, BigDecimal coupon) {
|
|
|
+ BigDecimal totalAmount = calcTotalAmount(orderItemList);
|
|
|
+ for (OmsOrderItem orderItem : orderItemList) {
|
|
|
+
|
|
|
+ BigDecimal couponAmount = orderItem.getProductPrice()
|
|
|
+ .divide(totalAmount, 2, BigDecimal.ROUND_DOWN)
|
|
|
+ .multiply(coupon);
|
|
|
+ orderItem.setCouponAmount(couponAmount);
|
|
|
+
|
|
|
+ orderItem.setPrecisionAmount(BigDecimal.ZERO);
|
|
|
+
|
|
|
+ }
|
|
|
+ BigDecimal reduce = orderItemList.stream()
|
|
|
+ .map(omsOrderItem -> omsOrderItem.getCouponAmount().multiply(BigDecimal.valueOf(omsOrderItem.getProductQuantity())))
|
|
|
+ .reduce(BigDecimal.ZERO, BigDecimal::add);
|
|
|
+ OmsOrderItem omsOrderItem = orderItemList.get(0);
|
|
|
+ omsOrderItem.setPrecisionAmount(coupon.subtract(reduce));
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ * 获取与优惠券有关系的下单商品
|
|
|
+ *
|
|
|
+ * @param couponHistoryDetail 优惠券详情
|
|
|
+ * @param orderItemList 下单商品
|
|
|
+ * @param type 使用关系类型:0->相关分类;1->指定商品
|
|
|
+ */
|
|
|
+ private List<OmsOrderItem> getCouponOrderItemByRelation(SmsCouponHistoryDetail couponHistoryDetail, List<OmsOrderItem> orderItemList, int type) {
|
|
|
+ List<OmsOrderItem> result = new ArrayList<>();
|
|
|
+ if (type == 0) {
|
|
|
+ List<Long> categoryIdList = new ArrayList<>();
|
|
|
+ for (SmsCouponProductCategoryRelation productCategoryRelation : couponHistoryDetail.getCategoryRelationList()) {
|
|
|
+ categoryIdList.add(productCategoryRelation.getProductCategoryId());
|
|
|
+ }
|
|
|
+ for (OmsOrderItem orderItem : orderItemList) {
|
|
|
+ if (categoryIdList.contains(orderItem.getProductCategoryId())) {
|
|
|
+ result.add(orderItem);
|
|
|
+ } else {
|
|
|
+ orderItem.setCouponAmount(new BigDecimal(0));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else if (type == 1) {
|
|
|
+ List<Long> productIdList = new ArrayList<>();
|
|
|
+ for (SmsCouponProductRelation productRelation : couponHistoryDetail.getProductRelationList()) {
|
|
|
+ productIdList.add(productRelation.getProductId());
|
|
|
+ }
|
|
|
+ for (OmsOrderItem orderItem : orderItemList) {
|
|
|
+ if (productIdList.contains(orderItem.getProductId())) {
|
|
|
+ result.add(orderItem);
|
|
|
+ } else {
|
|
|
+ orderItem.setCouponAmount(new BigDecimal(0));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ * 获取该用户可以使用的优惠券
|
|
|
+ *
|
|
|
+ * @param cartPromotionItemList 购物车优惠列表
|
|
|
+ * @param couponId 使用优惠券id
|
|
|
+ */
|
|
|
+ private SmsCouponHistoryDetail getUseCoupon(List<CartPromotionItem> cartPromotionItemList, Long couponId) {
|
|
|
+ List<SmsCouponHistoryDetail> couponHistoryDetailList = memberCouponService.listCart(cartPromotionItemList, 1);
|
|
|
+ for (SmsCouponHistoryDetail couponHistoryDetail : couponHistoryDetailList) {
|
|
|
+ if (couponHistoryDetail.getCoupon().getId().equals(couponId)) {
|
|
|
+ return couponHistoryDetail;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ * 计算总金额
|
|
|
+ */
|
|
|
+ private BigDecimal calcTotalAmount(List<OmsOrderItem> orderItemList) {
|
|
|
+ BigDecimal totalAmount = new BigDecimal("0");
|
|
|
+ for (OmsOrderItem item : orderItemList) {
|
|
|
+ totalAmount = totalAmount.add(item.getProductPrice().multiply(new BigDecimal(item.getProductQuantity())));
|
|
|
+ }
|
|
|
+ return totalAmount;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ * 锁定下单商品的所有库存
|
|
|
+ */
|
|
|
+ private void lockSkuStock(List<CartPromotionItem> cartPromotionItemList) {
|
|
|
+ for (CartPromotionItem cartPromotionItem : cartPromotionItemList) {
|
|
|
+ if (cartPromotionItem.getProductSkuId() == null) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ int i = skuStockMapper.lockStock(cartPromotionItem.getProductSkuId(), cartPromotionItem.getQuantity());
|
|
|
+ if (i == 0) {
|
|
|
+ Asserts.fail("库存不足");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ * 锁定下单商品的所有库存
|
|
|
+ */
|
|
|
+ private void lockProductStock(List<CartPromotionItem> cartPromotionItemList) {
|
|
|
+ Map<Long, List<CartPromotionItem>> collect = cartPromotionItemList.stream()
|
|
|
+ .collect(Collectors.groupingBy(
|
|
|
+ CartPromotionItem::getProductId));
|
|
|
+ for (Map.Entry<Long, List<CartPromotionItem>> entry : collect.entrySet()) {
|
|
|
+ List<CartPromotionItem> value = entry.getValue();
|
|
|
+ if (CollectionUtils.isEmpty(value)) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ int sum = value.stream().mapToInt(CartPromotionItem::getQuantity).sum();
|
|
|
+ if (sum > 0) {
|
|
|
+ int i = pmsProductMapper.lockStock(entry.getKey(), sum);
|
|
|
+ if (i == 0) {
|
|
|
+ Asserts.fail("库存不足");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ * 判断下单商品是否都有库存
|
|
|
+ */
|
|
|
+ private boolean hasStock(List<CartPromotionItem> cartPromotionItemList) {
|
|
|
+ for (CartPromotionItem cartPromotionItem : cartPromotionItemList) {
|
|
|
+ if (cartPromotionItem.getRealStock() == null || cartPromotionItem.getRealStock() <= 0) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ * 计算购物车中商品的价格
|
|
|
+ */
|
|
|
+ private ConfirmOrderResult.CalcAmount calcCartAmount(List<CartPromotionItem> cartPromotionItemList) {
|
|
|
+ ConfirmOrderResult.CalcAmount calcAmount = new ConfirmOrderResult.CalcAmount();
|
|
|
+ calcAmount.setFreightAmount(new BigDecimal(0));
|
|
|
+ BigDecimal totalAmount = new BigDecimal("0");
|
|
|
+ BigDecimal promotionAmount = new BigDecimal("0");
|
|
|
+ for (CartPromotionItem cartPromotionItem : cartPromotionItemList) {
|
|
|
+ totalAmount = totalAmount.add(
|
|
|
+ cartPromotionItem.getPrice().multiply(new BigDecimal(cartPromotionItem.getQuantity())));
|
|
|
+ promotionAmount = promotionAmount.add(
|
|
|
+ cartPromotionItem.getReduceAmount().multiply(new BigDecimal(cartPromotionItem.getQuantity())));
|
|
|
+ }
|
|
|
+ calcAmount.setTotalAmount(totalAmount);
|
|
|
+ calcAmount.setPromotionAmount(promotionAmount);
|
|
|
+ calcAmount.setPayAmount(totalAmount.subtract(promotionAmount));
|
|
|
+ return calcAmount;
|
|
|
+ }
|
|
|
+
|
|
|
+}
|