Merge remote-tracking branch 'origin/test' into test
This commit is contained in:
@@ -6,6 +6,7 @@ import org.mybatis.spring.annotation.MapperScan;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
|
||||
import org.springframework.scheduling.annotation.EnableAsync;
|
||||
import org.springframework.transaction.annotation.EnableTransactionManagement;
|
||||
|
||||
/**
|
||||
@@ -17,6 +18,7 @@ import org.springframework.transaction.annotation.EnableTransactionManagement;
|
||||
@MapperScan("com.czg.service.account.mapper")
|
||||
@EnableDubbo
|
||||
@Slf4j
|
||||
@EnableAsync
|
||||
public class AccountApplication{
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(AccountApplication.class, args);
|
||||
|
||||
@@ -6,10 +6,16 @@ spring:
|
||||
name: account
|
||||
profiles:
|
||||
active: dev
|
||||
include: tools
|
||||
servlet:
|
||||
multipart:
|
||||
max-file-size: 10MB
|
||||
task:
|
||||
execution:
|
||||
pool:
|
||||
core-size: 8
|
||||
max-size: 16
|
||||
queue-capacity: 200
|
||||
thread-name-prefix: async-account-
|
||||
|
||||
|
||||
logging:
|
||||
@@ -23,25 +29,6 @@ mybatis-flex:
|
||||
call-setters-on-nulls: true
|
||||
jdbc-type-for-null: 'null'
|
||||
|
||||
wx:
|
||||
appId: wxd88fffa983758a30
|
||||
secrete: a34a61adc0602118b49400baa8812454
|
||||
account:
|
||||
appId: wx212769170d2c6b2a
|
||||
secrete: 8492a7e8d55bbb1b57f5c8276ea1add0
|
||||
|
||||
alipay:
|
||||
serverUrl: https://openapi.alipay.com/gateway.do
|
||||
appId: 2021004145625815
|
||||
privateKey: MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCAjDBuS8K/IJb9ui+KuNm/sTUdEiaji4BNpZ92avO1N5JpNlGmac6ec4p3tNFT950sBLcQkClcUpQxUHQzAT6DYNNXOKyvfI/EmcqwCw6PaMNLs/8cV//J2WWZBUhLaOsjKurpm9/3W5MnTh4BGxIfBoeBMA8f8K3BgKdmyKtvIEV2h2cyjsMskdn+g6oNZcmWcms0pvpPHyH46mRaGFhpp0v19wX3WsamGldh1L2VntmaDN3C2XbSrXv90XYp5bEUqwTbLwXpMAlzTibF56d/iqv9oYi8cpAKougUFLOymnbutLNs2tLrEDSFwHcmG2/wbZHybZyYcIgFgv4arf+tAgMBAAECggEAf7hKKlw1y6Z6vvAtalxNZUuRZSfyog3p1bwYWxTavZPQcZ7Zs0lvVDmiO1u5m/7q96BbryY9IhCeUv0H5uF2lhwu/3s9AEL3qTPQkeb6eXxyhhX6A9RfPdM1Qbtg4CQHdHKg4qjP9znSVHwmDZ0y/QaEvdPdQzPjv92u9c2tn4N4x6XyBYcU5gzxiJNnIugCmBgcJo/3H2fgV+XXEhORPvy5of9b4oATHEaLS/8dAS2wuOjhzaGS4MXp3VkXn3XaYjwSzaL03qYWA+xm+aO5sJv8bmqZW7sNVck5o3sPo7cQ4VkBFVzyrRdmJcxcSRJ9MsB9JsrhoKI8pgaXrVie4QKBgQDU2vai0lpBIK/0jzRpPNoqdT8lnafnnWni8nU4kfAh+gCLi+HBPhQRT0kv4unQc2q2/gALE7sgZVO00JGY5a3R0orsojPoUSZlpypGW7GGqKy576NHn0nw4o/PdfysT92VWgt1hlfTf6qfCDhfE9APU+RGvlSWXcT8nxVel3iUaQKBgQCamoJN6+4v+chJvL2nqV8NVVRLp0vDIHxs1QOtKwUodx8Qp1D6CJYtavCXn8aNUFVNQJPJ7TQPpJjXP2rI4SN01weDwx+I+wh8PBGHV6/234R+6TvFgY1PrYgCdfNP4i/E7B4uyEhAxdU73PB8qkqRAeJGok05p7oG71KCOBiYpQKBgEZfGflcuDAeAW5GRhqg3rP4zWa/R7qgZVh9tll8jjp9b96y4XFE99d9MgId8BVVgyt6sEL5Q/2C4ni+F9TH4n6jMADp42VkJuCmsqhOOlP9whU67+2G8Sgtj0QUivPg964f9ffl8XVgGOW5DwIIB9p5btggptCLscufQK5kP545AoGADBvf6tR4wl8w9b2HqTMV08iEIqzGvVC1Dh0c/Zop/EJgN4CzUfIMOSBwGaAVAApzs+pD6QPgGP2OTwWTioo/qa4R05sbxDHNN1XJFa2jhZV6HiqMWOrNs5jm1zJ/zRjtHuJTdtyO9CvKiLbESy9XScY4/8lEfSiK5HIoJzTXkFUCgYAkYkvkW6psJpWj05XWq44UN0n6QOU/Igl35Um/iuOMVhsTmIt09STQVTuzJzfH82+sCqoRsD1blE5unKNUC1DK77aNKTv3Z0dxN9R7FAyfZRiYQXTrbBPBqWjay6FCNxn8e8UsJN4Z6FIV2LGlQI114krSap1MALKLVvnld0NaUQ==
|
||||
alipayPublicKey: MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAiQkrz+emAuS1mB3KKDOMmAZRd/BlPbh7fAIHAqAj1+QCZNcV3o2BTLIIqnuKpSlFXDG3uDzp2VsBxcizXuBbFyPGylnD9CgCj5abyh3+FIHPAZ2IM3TtpqImZ0TSPGXrMli4Nir7MvZktgccCqQKCC4o6iaDGz+UwWwJUIPna8fm2tiTZ+KH150CZbKVj4ZGNpBh5XSV/1dRgyQIV9D/EwSbkZ0n6VgKQLJBi0C2UE3QB17aL1Ir6+gDXIDbknN8O7GUD3aMGdThYdSRUb5wp9CZ5qfV7vCS/CgaRo38nhH3NOzkTL+7v0m1ZDHPmqEkn9VzZN6sCQdL7PoAOjHOCwIDAQAB
|
||||
encryptKey: Hp1TbhOqevbHCA5ji/VlqQ==
|
||||
account:
|
||||
appId: 2021004174605036
|
||||
privateKey: MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQD48HaUoV7OH7os+9L01kHgxzwIhJick4OkFq4aHsntsXEJ J3gedhuEZtV8oHKZ30DPW12IJ4S8NXtpr8OWaqrAPFonf4wVaRY1d0yIAea57kfLEn9oOEEy4FzARgMNDkyxC+/3OUdGbLHpTjfVX3gusXsEhUDy1/WewihAkoNYF37+W3W/uVLzeWoPq0EcUbRv/G/t/p6gL69ltsMAiVFG4Q/Yk24YAN6lYgBPNLXUEwQ1Q+T+1omjfavHgvarKOp33z3JOUH+aGOmDsJ5Y9gyGtJzOCipAd8Zcv+T1ygsEzZYO1/gzcbPnfO1ShqStCHzssuw8FBVx2JdfQKXKMMNAgMBAAECggEAVTrO/pg5Q00titU1Jspsh67u6OOs9H605Ws2dI7yB8VmtAGlaJh7V1t14FN2qSP8poHbhhAxq9aLyGV7C3a9u09udnN+3J28EtYjh7VO732bavWMVXxdJjQWzWWrCb9JlpxFrlkYBA6W4w/6ob0sAqCVQ7jzwbEa0R4cde8ztOa5nysKSfr4YTSs0gqvoiC6fmg8eiRJraEQBoYz9VkKFtOhhh/4w5FhVcYQ2gQvZ3kK3QVuD1eJIQKlCtz8qaox9lXKDiZT4SCmnKshdUL0u5TYIcYeBjZmhJz0Q50KHcpZrCs5y7I0+vRBH3hU+TKSQt7ureymwhbwWMHScLV2gQKBgQD+58SHXhr5M8NGagAmTdsgmCnNv2kOYMd4STyPMY10SVwCv1Bk808ZuP+7e558J1b5/OuDLI5dLq6xrZ/1wLv1G++XqxI00hlFuWS5mUGJVcXotT1mw20rVeUILc7Qe3mLvbMGgfyKf4A7Qa5SSZ4bDeDTJYaFxyiQ281hMzDuPQKBgQD6AiL/Na2/uPH4CG6juwpjYvYVUcjK+7gbRwf3wWsWMpk90Z4ju2iUiP5c1J/oK9P+1T3PIr6M4Xjza8JJj+r9KC/PVB0gBv6vVM96cDpKUEy/UMpcn/T81vqj/Z+WEOODU8Ms6NiTTm+u9ldvpCjbu0u8M+9c0JeIyadJvSTFEQKBgQCsxmFyM3nq8YfpgU2qqNjfBeRH3faSVUy+nj1a/YZYjKS+A/i1BCnYUImeBVNN6chNV342ggvY4xxruDiU9Vcw8wd58O09Oi8BEIFSP6upL6cebUI6Fjo3xlegLJRiwV6INkNTJOYM5hD/mSxUACwXQFfkJipBINXBIgraWD1RLQKBgQCj49axWq0F6+WjZVOyPaD3uh37p9trRUxRhWTxw3fB23WdktaKMgbCqHOmwzP4bRLSEVQtf2dOz1gMqu14b8HqJvgAf/F/11YJ9hz09LEhmjZVjE68HZfqT7uK2W5OX8/lfXmK7TFcj6SjG5YB96lZMhTZ0WnufEd6QkdKDZYXIQKBgQD9GDTcIMbFwbEaKHnfZaTD3f876EGRgsgrCxwdEk7LBCRPwWo7yI929M4psIlpNwNeiyjBkBunWIVkpznp6qPtJqagIPUYesU4f5v6/okq5wcpaNKSkWbIvWVLaLGOiA1aeGJtbpMpyClbSr52puHpRRdvAiIEQ74yYh0JX8q96g==
|
||||
publicKey: MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAiQkrz+emAuS1mB3KKDOMmAZRd/BlPbh7fAIHAqAj1+QCZNcV3o2BTLIIqnuKpSlFXDG3uDzp2VsBxcizXuBbFyPGylnD9CgCj5abyh3+FIHPAZ2IM3TtpqImZ0TSPGXrMli4Nir7MvZktgccCqQKCC4o6iaDGz+UwWwJUIPna8fm2tiTZ+KH150CZbKVj4ZGNpBh5XSV/1dRgyQIV9D/EwSbkZ0n6VgKQLJBi0C2UE3QB17aL1Ir6+gDXIDbknN8O7GUD3aMGdThYdSRUb5wp9CZ5qfV7vCS/CgaRo38nhH3NOzkTL+7v0m1ZDHPmqEkn9VzZN6sCQdL7PoAOjHOCwIDAQAB
|
||||
|
||||
|
||||
|
||||
pagehelper:
|
||||
helper-dialect: mysql
|
||||
|
||||
@@ -6,6 +6,7 @@ import org.mybatis.spring.annotation.MapperScan;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
|
||||
import org.springframework.scheduling.annotation.EnableAsync;
|
||||
import org.springframework.scheduling.annotation.EnableScheduling;
|
||||
import org.springframework.transaction.annotation.EnableTransactionManagement;
|
||||
|
||||
@@ -21,6 +22,7 @@ import javax.annotation.PostConstruct;
|
||||
@EnableDubbo
|
||||
@EnableScheduling
|
||||
@Slf4j
|
||||
@EnableAsync
|
||||
public class MarketApplication {
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(MarketApplication.class, args);
|
||||
|
||||
@@ -6,15 +6,13 @@ spring:
|
||||
name: market
|
||||
profiles:
|
||||
active: dev
|
||||
include: tools
|
||||
wx:
|
||||
ysk:
|
||||
appId: wx212769170d2c6b2a
|
||||
secrete: 8492a7e8d55bbb1b57f5c8276ea1add0
|
||||
operationMsgTmpId: wFdoUG-dUT7bDRHq8bMJD9CF5TjyH9x_uJQgQByZqHg
|
||||
warnMsgTmpId: C08OUr80x6wGmUN1zpFhSQ3Sv7VF5vksdZigiEx2pD0
|
||||
|
||||
|
||||
task:
|
||||
execution:
|
||||
pool:
|
||||
core-size: 8
|
||||
max-size: 16
|
||||
queue-capacity: 200
|
||||
thread-name-prefix: async-product-
|
||||
|
||||
logging:
|
||||
config: classpath:logback.xml
|
||||
|
||||
@@ -5,6 +5,7 @@ import org.mybatis.spring.annotation.MapperScan;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
|
||||
import org.springframework.scheduling.annotation.EnableAsync;
|
||||
import org.springframework.scheduling.annotation.EnableScheduling;
|
||||
import org.springframework.transaction.annotation.EnableTransactionManagement;
|
||||
|
||||
@@ -17,6 +18,7 @@ import org.springframework.transaction.annotation.EnableTransactionManagement;
|
||||
@EnableDubbo
|
||||
@SpringBootApplication
|
||||
@EnableScheduling
|
||||
@EnableAsync
|
||||
public class OrderApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
@@ -6,7 +6,9 @@ import com.czg.order.entity.ShopProdStatistic;
|
||||
import com.czg.order.param.DataSummaryTradeParam;
|
||||
import com.czg.order.service.ShopOrderStatisticService;
|
||||
import com.czg.order.service.ShopProdStatisticService;
|
||||
import com.czg.order.vo.CostLineChartVO;
|
||||
import com.czg.order.vo.CountPayTypeVo;
|
||||
import com.czg.order.vo.ProfitRateVO;
|
||||
import com.czg.order.vo.TotalVo;
|
||||
import com.czg.resp.CzgResult;
|
||||
import com.czg.sa.StpKit;
|
||||
@@ -71,7 +73,7 @@ public class DataSummaryController {
|
||||
}
|
||||
|
||||
/**
|
||||
* 销售趋势柱状图 左下
|
||||
* 销售趋势柱状图 左下1
|
||||
*
|
||||
* @param day 天数
|
||||
* @param shopId 店铺id
|
||||
@@ -88,7 +90,7 @@ public class DataSummaryController {
|
||||
}
|
||||
|
||||
/**
|
||||
* 支付占比饼图 左下
|
||||
* 支付占比饼图 左下2
|
||||
*
|
||||
* @param day 天数
|
||||
* @param shopId 店铺id
|
||||
@@ -102,4 +104,38 @@ public class DataSummaryController {
|
||||
List<CountPayTypeVo> data = orderStatisticService.getSummaryPayTypeData(shopId, day);
|
||||
return CzgResult.success(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 毛利率/净利率 柱状图 左下下
|
||||
* 利润率柱状图
|
||||
* @param day 天数
|
||||
* @param shopId 店铺id
|
||||
*/
|
||||
@GetMapping("profitRateBarChart")
|
||||
@SaAdminCheckPermission(value = "dataSummary:profitRateBarChart", name = "毛利率/净利率柱状图 左下下")
|
||||
public CzgResult<List<ProfitRateVO>> profitRateBarChart(@RequestParam Integer day, @RequestParam(required = false) Long shopId) {
|
||||
AssertUtil.isNull(day, "天数不能为空");
|
||||
if (shopId == null) {
|
||||
shopId = StpKit.USER.getShopId();
|
||||
}
|
||||
List<ProfitRateVO> data = orderStatisticService.profitRateBarChart(shopId, day);
|
||||
return CzgResult.success(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 成本折线图 右下下
|
||||
* @param day 天数
|
||||
* @param shopId 店铺id
|
||||
*/
|
||||
@GetMapping("costLineChart")
|
||||
@SaAdminCheckPermission(value = "dataSummary:costLineChart", name = "成本折线图 右下下")
|
||||
public CzgResult<List<CostLineChartVO>> costLineChart(@RequestParam Integer day, @RequestParam(required = false) Long shopId) {
|
||||
AssertUtil.isNull(day, "天数不能为空");
|
||||
if (shopId == null) {
|
||||
shopId = StpKit.USER.getShopId();
|
||||
}
|
||||
List<CostLineChartVO> data = orderStatisticService.costLineChart(shopId, day);
|
||||
return CzgResult.success(data);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -6,7 +6,13 @@ spring:
|
||||
name: order
|
||||
profiles:
|
||||
active: dev
|
||||
include: tools
|
||||
task:
|
||||
execution:
|
||||
pool:
|
||||
core-size: 8
|
||||
max-size: 16
|
||||
queue-capacity: 200
|
||||
thread-name-prefix: async-order-
|
||||
|
||||
|
||||
logging:
|
||||
|
||||
@@ -5,6 +5,7 @@ import org.mybatis.spring.annotation.MapperScan;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
import org.springframework.transaction.annotation.EnableTransactionManagement;
|
||||
|
||||
/**
|
||||
@@ -15,6 +16,7 @@ import org.springframework.transaction.annotation.EnableTransactionManagement;
|
||||
@EnableTransactionManagement
|
||||
@EnableDubbo
|
||||
@MapperScan("com.czg.service.product.mapper")
|
||||
@Async
|
||||
public class ProductApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
@@ -6,20 +6,22 @@ spring:
|
||||
name: product
|
||||
profiles:
|
||||
active: dev
|
||||
include: tools
|
||||
servlet:
|
||||
multipart:
|
||||
max-file-size: 10MB
|
||||
task:
|
||||
execution:
|
||||
pool:
|
||||
core-size: 8
|
||||
max-size: 16
|
||||
queue-capacity: 200
|
||||
thread-name-prefix: async-product-
|
||||
wx:
|
||||
ysk:
|
||||
appId: wx212769170d2c6b2a
|
||||
secrete: 8492a7e8d55bbb1b57f5c8276ea1add0
|
||||
operationMsgTmpId: wFdoUG-dUT7bDRHq8bMJD9CF5TjyH9x_uJQgQByZqHg
|
||||
warnMsgTmpId: C08OUr80x6wGmUN1zpFhSQ3Sv7VF5vksdZigiEx2pD0
|
||||
# 公众号
|
||||
ac:
|
||||
appId: wx1fb600d0f5ea6279
|
||||
secrete: b4c0534c9b5e6c84a7fe5c2078dff876
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ import org.mybatis.spring.annotation.MapperScan;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
|
||||
import org.springframework.scheduling.annotation.EnableAsync;
|
||||
import org.springframework.scheduling.annotation.EnableScheduling;
|
||||
import org.springframework.transaction.annotation.EnableTransactionManagement;
|
||||
|
||||
@@ -17,6 +18,7 @@ import org.springframework.transaction.annotation.EnableTransactionManagement;
|
||||
@MapperScan("com.czg.service.system.mapper")
|
||||
@EnableDubbo
|
||||
@EnableScheduling
|
||||
@EnableAsync
|
||||
public class SystemApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
@@ -6,6 +6,13 @@ spring:
|
||||
name: system
|
||||
profiles:
|
||||
active: dev
|
||||
task:
|
||||
execution:
|
||||
pool:
|
||||
core-size: 8
|
||||
max-size: 16
|
||||
queue-capacity: 200
|
||||
thread-name-prefix: async-system-
|
||||
|
||||
|
||||
logging:
|
||||
@@ -15,12 +22,6 @@ pagehelper:
|
||||
helper-dialect: mysql
|
||||
support-methods-arguments: true
|
||||
|
||||
alipay:
|
||||
sms:
|
||||
key: your-key
|
||||
secret: your-secret
|
||||
templateCode: c
|
||||
|
||||
dubbo:
|
||||
provider:
|
||||
filter: traceProviderFilter
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package com.czg.order.service;
|
||||
|
||||
import com.czg.order.vo.CostLineChartVO;
|
||||
import com.czg.order.vo.CountPayTypeVo;
|
||||
import com.czg.order.vo.ProfitRateVO;
|
||||
import com.czg.order.vo.TotalVo;
|
||||
import com.mybatisflex.core.service.IService;
|
||||
import com.czg.order.entity.ShopOrderStatistic;
|
||||
@@ -40,6 +42,16 @@ public interface ShopOrderStatisticService extends IService<ShopOrderStatistic>
|
||||
* 获取支付方式数据
|
||||
*/
|
||||
List<CountPayTypeVo> getSummaryPayTypeData(Long shopId, Integer day);
|
||||
/**
|
||||
* 利润率折线图
|
||||
*/
|
||||
List<ProfitRateVO> profitRateBarChart(Long shopId, Integer day);
|
||||
|
||||
/**
|
||||
* 成本折线图
|
||||
*/
|
||||
List<CostLineChartVO> costLineChart(Long shopId, Integer day);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
package com.czg.order.vo;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* 成本折线图 左下下
|
||||
*
|
||||
* @author ww
|
||||
*/
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
public class CostLineChartVO implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 成本价
|
||||
*/
|
||||
private BigDecimal productCostAmount;
|
||||
/**
|
||||
* 日期
|
||||
*/
|
||||
@JsonFormat(pattern = "yyyy-MM-dd")
|
||||
private LocalDate tradeDay;
|
||||
|
||||
|
||||
public CostLineChartVO(LocalDate tradeDay) {
|
||||
this.tradeDay = tradeDay;
|
||||
}
|
||||
|
||||
/**
|
||||
* 合并实时数据和历史数据,并填充缺失的日期
|
||||
*/
|
||||
public static List<CostLineChartVO> mergeAndFillData(CostLineChartVO onlineData, List<CostLineChartVO> historyData,
|
||||
LocalDate startDate, LocalDate endDate) {
|
||||
// 创建日期到数据的映射,方便查找
|
||||
Map<LocalDate, CostLineChartVO> dataMap = new HashMap<>();
|
||||
|
||||
// 将历史数据放入映射
|
||||
for (CostLineChartVO vo : historyData) {
|
||||
if (vo.getTradeDay() != null) {
|
||||
dataMap.put(vo.getTradeDay(), vo);
|
||||
}
|
||||
}
|
||||
dataMap.put(onlineData.getTradeDay(), onlineData);
|
||||
|
||||
List<CostLineChartVO> result = new ArrayList<>();
|
||||
LocalDate currentDay = startDate;
|
||||
|
||||
while (!currentDay.isAfter(endDate)) {
|
||||
if (dataMap.containsKey(currentDay)) {
|
||||
result.add(dataMap.get(currentDay));
|
||||
} else {
|
||||
// 创建空的TotalVo填充缺失的日期
|
||||
CostLineChartVO emptyVo = new CostLineChartVO(currentDay);
|
||||
result.add(emptyVo);
|
||||
}
|
||||
currentDay = currentDay.plusDays(1);
|
||||
}
|
||||
// 按日期排序确保顺序正确
|
||||
result.sort(Comparator.comparing(CostLineChartVO::getTradeDay));
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -40,6 +40,21 @@ public class CountPayTypeVo {
|
||||
PAY_TYPE_MAPPING.put("creditPay", "挂账支付");
|
||||
}
|
||||
|
||||
/**
|
||||
* 实时数据
|
||||
*/
|
||||
public static List<CountPayTypeVo> realTimeDataByDay(Map<String, BigDecimal> realTimeData) {
|
||||
List<CountPayTypeVo> result = new ArrayList<>();
|
||||
for (Map.Entry<String, String> entry : PAY_TYPE_MAPPING.entrySet()) {
|
||||
String payCode = entry.getKey();
|
||||
String payName = entry.getValue();
|
||||
|
||||
BigDecimal totalCount = getSafeValue(realTimeData, payCode);
|
||||
result.add(new CountPayTypeVo(totalCount.intValue(), payName));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 合并实时数据和历史统计数据
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
package com.czg.order.vo;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.util.*;
|
||||
|
||||
|
||||
/**
|
||||
* 毛利率/净利率 柱状图 左下下
|
||||
* 利润率柱状图
|
||||
*
|
||||
* @author ww
|
||||
*/
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
public class ProfitRateVO implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 毛利率
|
||||
*/
|
||||
private BigDecimal profitRate;
|
||||
/**
|
||||
* 净利润率
|
||||
*/
|
||||
private BigDecimal netProfitRate;
|
||||
/**
|
||||
* 日期
|
||||
*/
|
||||
@JsonFormat(pattern = "yyyy-MM-dd")
|
||||
private LocalDate tradeDay;
|
||||
|
||||
|
||||
public ProfitRateVO(LocalDate tradeDay) {
|
||||
this.tradeDay = tradeDay;
|
||||
}
|
||||
|
||||
/**
|
||||
* 合并实时数据和历史数据,并填充缺失的日期
|
||||
*/
|
||||
public static List<ProfitRateVO> mergeAndFillData(ProfitRateVO onlineData, List<ProfitRateVO> historyData,
|
||||
LocalDate startDate, LocalDate endDate) {
|
||||
// 创建日期到数据的映射,方便查找
|
||||
Map<LocalDate, ProfitRateVO> dataMap = new HashMap<>();
|
||||
|
||||
// 将历史数据放入映射
|
||||
for (ProfitRateVO vo : historyData) {
|
||||
if (vo.getTradeDay() != null) {
|
||||
dataMap.put(vo.getTradeDay(), vo);
|
||||
}
|
||||
}
|
||||
dataMap.put(onlineData.getTradeDay(), onlineData);
|
||||
|
||||
List<ProfitRateVO> result = new ArrayList<>();
|
||||
LocalDate currentDay = startDate;
|
||||
|
||||
while (!currentDay.isAfter(endDate)) {
|
||||
if (dataMap.containsKey(currentDay)) {
|
||||
result.add(dataMap.get(currentDay));
|
||||
} else {
|
||||
// 创建空的TotalVo填充缺失的日期
|
||||
ProfitRateVO emptyVo = new ProfitRateVO(currentDay);
|
||||
result.add(emptyVo);
|
||||
}
|
||||
currentDay = currentDay.plusDays(1);
|
||||
}
|
||||
// 按日期排序确保顺序正确
|
||||
result.sort(Comparator.comparing(ProfitRateVO::getTradeDay));
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
alipay:
|
||||
sms:
|
||||
key: LTAI5tPdEfYSZcqHbjCrtPRD
|
||||
secret: DZjyHBq3nTujF0NMLxnZgsecU8ZCvy
|
||||
templateCode: SMS_244665149
|
||||
@@ -1,7 +1,9 @@
|
||||
package com.czg.service.order.mapper;
|
||||
|
||||
import com.czg.order.entity.ShopOrderStatistic;
|
||||
import com.czg.order.vo.CostLineChartVO;
|
||||
import com.czg.order.vo.ProductCostAmountVO;
|
||||
import com.czg.order.vo.ProfitRateVO;
|
||||
import com.czg.order.vo.TotalVo;
|
||||
import com.mybatisflex.core.BaseMapper;
|
||||
import org.apache.ibatis.annotations.Select;
|
||||
@@ -141,6 +143,31 @@ public interface ShopOrderStatisticMapper extends BaseMapper<ShopOrderStatistic>
|
||||
Map<String, BigDecimal> getPayTypeDateRangeRaw(Long shopId, LocalDate start, LocalDate end);
|
||||
|
||||
|
||||
@Select("SELECT" +
|
||||
" profit_rate as profitRate, " +
|
||||
" net_profit_rate as netProfitRate, " +
|
||||
" statistic_date as tradeDay" +
|
||||
" FROM" +
|
||||
" tb_shop_order_statistic " +
|
||||
" WHERE" +
|
||||
" shop_id = #{shopId} " +
|
||||
"and statistic_date >= #{start} " +
|
||||
"and statistic_date <= #{end} ")
|
||||
List<ProfitRateVO> profitRateBarChart(Long shopId, LocalDate start, LocalDate end);
|
||||
|
||||
|
||||
@Select("SELECT" +
|
||||
" product_cost_amount as productCostAmount, " +
|
||||
" statistic_date as tradeDay" +
|
||||
" FROM" +
|
||||
" tb_shop_order_statistic " +
|
||||
" WHERE" +
|
||||
" shop_id = #{shopId} " +
|
||||
"and statistic_date >= #{start} " +
|
||||
"and statistic_date <= #{end} ")
|
||||
List<CostLineChartVO> costLineChart(Long shopId, LocalDate start, LocalDate end);
|
||||
|
||||
|
||||
//*********************以下为日常统计********************************************************************************
|
||||
|
||||
|
||||
|
||||
@@ -6,9 +6,7 @@ import cn.hutool.core.collection.CollUtil;
|
||||
import com.czg.exception.CzgException;
|
||||
import com.czg.order.entity.ShopOrderStatistic;
|
||||
import com.czg.order.service.ShopOrderStatisticService;
|
||||
import com.czg.order.vo.CountPayTypeVo;
|
||||
import com.czg.order.vo.ProductCostAmountVO;
|
||||
import com.czg.order.vo.TotalVo;
|
||||
import com.czg.order.vo.*;
|
||||
import com.czg.service.order.mapper.ShopOrderStatisticMapper;
|
||||
import com.mybatisflex.core.query.QueryWrapper;
|
||||
import com.mybatisflex.spring.service.impl.ServiceImpl;
|
||||
@@ -65,23 +63,56 @@ public class ShopOrderStatisticServiceImpl extends ServiceImpl<ShopOrderStatisti
|
||||
@Override
|
||||
public List<TotalVo> getDateAmount(Long shopId, Integer day) {
|
||||
LocalDate currentDate = LocalDate.now();
|
||||
LocalDate startDate = currentDate;
|
||||
if (day == 7) {
|
||||
startDate = currentDate.minusDays(6);
|
||||
} else if (day == 30) {
|
||||
startDate = currentDate.minusDays(29);
|
||||
}
|
||||
LocalDate startDate;
|
||||
TotalVo onlineDataAmount = mapper.getOnlineDataAmount(shopId, currentDate);
|
||||
if (onlineDataAmount == null) {
|
||||
onlineDataAmount = new TotalVo(currentDate);
|
||||
}
|
||||
if (day <= 1) {
|
||||
return List.of(onlineDataAmount);
|
||||
}else {
|
||||
startDate = currentDate.minusDays(day - 1);
|
||||
}
|
||||
List<TotalVo> statDateRange = mapper.getStatDateRange(shopId, startDate, currentDate);
|
||||
|
||||
return TotalVo.mergeAndFillData(onlineDataAmount, statDateRange, startDate, currentDate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<CountPayTypeVo> getSummaryPayTypeData(Long shopId, Integer day) {
|
||||
LocalDate currentDate = LocalDate.now();
|
||||
LocalDate startDate;
|
||||
if (day <= 1) {
|
||||
Map<String, BigDecimal> onlinePayTypeDate = mapper.getOnlinePayTypeDate(shopId, currentDate);
|
||||
return CountPayTypeVo.realTimeDataByDay(onlinePayTypeDate);
|
||||
}else {
|
||||
startDate = currentDate.minusDays(day - 1);
|
||||
}
|
||||
return CountPayTypeVo.mergePayTypeData(
|
||||
mapper.getOnlinePayTypeDate(shopId, currentDate),
|
||||
mapper.getPayTypeDateRangeRaw(shopId, startDate, currentDate));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ProfitRateVO> profitRateBarChart(Long shopId, Integer day) {
|
||||
LocalDate currentDate = LocalDate.now();
|
||||
LocalDate startDate;
|
||||
ShopOrderStatistic onlineDataAmount = getRealTimeDataByDay(shopId, currentDate);
|
||||
ProfitRateVO onlineProfitRateBarChart = new ProfitRateVO(currentDate);
|
||||
if (onlineDataAmount != null) {
|
||||
onlineProfitRateBarChart.setProfitRate(onlineDataAmount.getProfitRate());
|
||||
onlineProfitRateBarChart.setNetProfitRate(onlineDataAmount.getNetProfitRate());
|
||||
}
|
||||
if (day <= 1) {
|
||||
return List.of(onlineProfitRateBarChart);
|
||||
}else {
|
||||
startDate = currentDate.minusDays(day - 1);
|
||||
}
|
||||
List<ProfitRateVO> statDateRange = mapper.profitRateBarChart(shopId, startDate, currentDate);
|
||||
return ProfitRateVO.mergeAndFillData(onlineProfitRateBarChart, statDateRange, startDate, currentDate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<CostLineChartVO> costLineChart(Long shopId, Integer day) {
|
||||
LocalDate currentDate = LocalDate.now();
|
||||
LocalDate startDate = currentDate;
|
||||
if (day == 7) {
|
||||
@@ -89,11 +120,17 @@ public class ShopOrderStatisticServiceImpl extends ServiceImpl<ShopOrderStatisti
|
||||
} else if (day == 30) {
|
||||
startDate = currentDate.minusDays(29);
|
||||
}
|
||||
return CountPayTypeVo.mergePayTypeData(
|
||||
mapper.getOnlinePayTypeDate(shopId, currentDate),
|
||||
mapper.getPayTypeDateRangeRaw(shopId, startDate, currentDate));
|
||||
CostLineChartVO onlineCostLineChart = new CostLineChartVO(currentDate);
|
||||
BigDecimal productCostAmount = getProductCostAmount(shopId, currentDate);
|
||||
onlineCostLineChart.setProductCostAmount(productCostAmount);
|
||||
|
||||
List<CostLineChartVO> statDateRange = mapper.costLineChart(shopId, startDate, currentDate);
|
||||
return CostLineChartVO.mergeAndFillData(onlineCostLineChart, statDateRange, startDate, currentDate);
|
||||
}
|
||||
|
||||
|
||||
//u--------------------------------------------------_---------------------------------------------------------
|
||||
|
||||
@Override
|
||||
public void statisticAndInsert(Long shopId, LocalDate day) {
|
||||
ShopOrderStatistic realTimeData = getRealTimeDataByDay(shopId, day);
|
||||
@@ -185,7 +222,7 @@ public class ShopOrderStatisticServiceImpl extends ServiceImpl<ShopOrderStatisti
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取商品成本价
|
||||
* 获取商品总成本价
|
||||
*/
|
||||
private BigDecimal getProductCostAmount(Long shopId, LocalDate day) {
|
||||
BigDecimal productCostAmount = BigDecimal.ZERO;
|
||||
@@ -223,43 +260,77 @@ public class ShopOrderStatisticServiceImpl extends ServiceImpl<ShopOrderStatisti
|
||||
return productCostAmount;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 统一入口方法
|
||||
* 计算 客单价 翻台率 净利润 净利率 毛利润 毛利率
|
||||
*/
|
||||
private void calculateShopOrderStatistic(ShopOrderStatistic result) {
|
||||
//毛利润(订单实付金额-商品成本)
|
||||
calculateProfitInfo(result);
|
||||
calculateAvgPayAmount(result);
|
||||
calculateTurnoverRate(result);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 计算毛利润、毛利率(净利润、净利率与之一致)
|
||||
*/
|
||||
private void calculateProfitInfo(ShopOrderStatistic result) {
|
||||
// 初始化商品成本金额(避免null)
|
||||
if (result.getProductCostAmount() == null) {
|
||||
result.setProductCostAmount(BigDecimal.ZERO);
|
||||
}
|
||||
result.setProfitAmount(result.getPayAmount().subtract(result.getProductCostAmount()));
|
||||
//毛利率(订单实付金额-商品成本)/订单实付金额*100%
|
||||
|
||||
// 计算毛利润(订单实付金额-商品成本)
|
||||
BigDecimal profitAmount = result.getPayAmount().subtract(result.getProductCostAmount());
|
||||
result.setProfitAmount(profitAmount);
|
||||
|
||||
// 计算毛利率((订单实付金额-商品成本)/订单实付金额*100%)
|
||||
BigDecimal profitRate = BigDecimal.ZERO;
|
||||
if (result.getPayAmount().compareTo(BigDecimal.ZERO) > 0) {
|
||||
BigDecimal profitRate = result.getProfitAmount().divide(result.getPayAmount(), 4, RoundingMode.HALF_DOWN).multiply(BigDecimal.valueOf(100));
|
||||
profitRate = profitAmount.divide(result.getPayAmount(), 4, RoundingMode.HALF_DOWN)
|
||||
.multiply(BigDecimal.valueOf(100));
|
||||
}
|
||||
result.setProfitRate(profitRate);
|
||||
} else {
|
||||
result.setProfitRate(BigDecimal.ZERO);
|
||||
|
||||
// 净利润、净利率目前和毛利润、毛利率一致
|
||||
result.setNetProfitAmount(profitAmount);
|
||||
result.setNetProfitRate(profitRate);
|
||||
}
|
||||
//净利润 净利率 目前和 毛利润 毛利率 一致
|
||||
result.setNetProfitRate(result.getProfitRate());
|
||||
result.setNetProfitAmount(result.getProfitAmount());
|
||||
//客单价 实付金额(包括线上支付 包含现金支付 包含会员支付 包含挂账)/就餐人数
|
||||
|
||||
/**
|
||||
* 计算客单价
|
||||
* 客单价 = 实付金额 / 就餐人数(就餐人数为0时直接使用实付金额)
|
||||
*/
|
||||
private void calculateAvgPayAmount(ShopOrderStatistic result) {
|
||||
BigDecimal avgPayAmount;
|
||||
// 校验就餐人数有效性
|
||||
if (result.getCustomerCount() != null && result.getCustomerCount() > 0) {
|
||||
result.setAvgPayAmount(result.getPayAmount().divide(new BigDecimal(result.getCustomerCount()), 2, RoundingMode.HALF_DOWN));
|
||||
avgPayAmount = result.getPayAmount().divide(
|
||||
new BigDecimal(result.getCustomerCount()), 2, RoundingMode.HALF_DOWN
|
||||
);
|
||||
} else {
|
||||
result.setAvgPayAmount(result.getPayAmount());
|
||||
avgPayAmount = result.getPayAmount();
|
||||
}
|
||||
//翻台率 (订单数-桌台数)/桌台数*100%
|
||||
result.setAvgPayAmount(avgPayAmount);
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算翻台率
|
||||
* 翻台率 = (订单数-桌台数)/桌台数*100%(差值≤0时翻台率为0)
|
||||
*/
|
||||
private void calculateTurnoverRate(ShopOrderStatistic result) {
|
||||
BigDecimal turnoverRate = BigDecimal.ZERO;
|
||||
|
||||
// 校验桌台数有效性
|
||||
if (result.getTableCount() != null && result.getTableCount() > 0) {
|
||||
long orderTableDifference = result.getOrderCount() - result.getTableCount();
|
||||
BigDecimal turnoverRate = BigDecimal.ZERO;
|
||||
// 仅当差值大于0时计算翻台率
|
||||
if (orderTableDifference > 0) {
|
||||
turnoverRate = new BigDecimal(orderTableDifference).divide(new BigDecimal(result.getTableCount()), 2, RoundingMode.HALF_DOWN);
|
||||
turnoverRate = new BigDecimal(orderTableDifference)
|
||||
.divide(new BigDecimal(result.getTableCount()), 2, RoundingMode.HALF_DOWN);
|
||||
}
|
||||
}
|
||||
result.setTurnoverRate(turnoverRate);
|
||||
} else {
|
||||
result.setTurnoverRate(BigDecimal.ZERO);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user