diff --git a/cash-api/account-server/src/main/java/com/czg/AccountApplication.java b/cash-api/account-server/src/main/java/com/czg/AccountApplication.java index 9d7588165..2e1cfe566 100644 --- a/cash-api/account-server/src/main/java/com/czg/AccountApplication.java +++ b/cash-api/account-server/src/main/java/com/czg/AccountApplication.java @@ -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); diff --git a/cash-api/account-server/src/main/resources/application.yml b/cash-api/account-server/src/main/resources/application.yml index 9d8745ec9..d46b3b608 100644 --- a/cash-api/account-server/src/main/resources/application.yml +++ b/cash-api/account-server/src/main/resources/application.yml @@ -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 diff --git a/cash-api/market-server/src/main/java/com/czg/MarketApplication.java b/cash-api/market-server/src/main/java/com/czg/MarketApplication.java index 9319019b7..26bc71a34 100644 --- a/cash-api/market-server/src/main/java/com/czg/MarketApplication.java +++ b/cash-api/market-server/src/main/java/com/czg/MarketApplication.java @@ -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); diff --git a/cash-api/market-server/src/main/resources/application.yml b/cash-api/market-server/src/main/resources/application.yml index bb6c5c30c..4ca04c452 100644 --- a/cash-api/market-server/src/main/resources/application.yml +++ b/cash-api/market-server/src/main/resources/application.yml @@ -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 diff --git a/cash-api/order-server/src/main/java/com/czg/OrderApplication.java b/cash-api/order-server/src/main/java/com/czg/OrderApplication.java index 4d4cc9ab1..60eabb789 100644 --- a/cash-api/order-server/src/main/java/com/czg/OrderApplication.java +++ b/cash-api/order-server/src/main/java/com/czg/OrderApplication.java @@ -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) { diff --git a/cash-api/order-server/src/main/java/com/czg/controller/admin/DataSummaryController.java b/cash-api/order-server/src/main/java/com/czg/controller/admin/DataSummaryController.java index a3e9a829d..1bd970ad7 100644 --- a/cash-api/order-server/src/main/java/com/czg/controller/admin/DataSummaryController.java +++ b/cash-api/order-server/src/main/java/com/czg/controller/admin/DataSummaryController.java @@ -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 data = orderStatisticService.getSummaryPayTypeData(shopId, day); return CzgResult.success(data); } + + /** + * 毛利率/净利率 柱状图 左下下 + * 利润率柱状图 + * @param day 天数 + * @param shopId 店铺id + */ + @GetMapping("profitRateBarChart") + @SaAdminCheckPermission(value = "dataSummary:profitRateBarChart", name = "毛利率/净利率柱状图 左下下") + public CzgResult> profitRateBarChart(@RequestParam Integer day, @RequestParam(required = false) Long shopId) { + AssertUtil.isNull(day, "天数不能为空"); + if (shopId == null) { + shopId = StpKit.USER.getShopId(); + } + List data = orderStatisticService.profitRateBarChart(shopId, day); + return CzgResult.success(data); + } + + /** + * 成本折线图 右下下 + * @param day 天数 + * @param shopId 店铺id + */ + @GetMapping("costLineChart") + @SaAdminCheckPermission(value = "dataSummary:costLineChart", name = "成本折线图 右下下") + public CzgResult> costLineChart(@RequestParam Integer day, @RequestParam(required = false) Long shopId) { + AssertUtil.isNull(day, "天数不能为空"); + if (shopId == null) { + shopId = StpKit.USER.getShopId(); + } + List data = orderStatisticService.costLineChart(shopId, day); + return CzgResult.success(data); + } + } diff --git a/cash-api/order-server/src/main/resources/application.yml b/cash-api/order-server/src/main/resources/application.yml index 4ba37f26b..905304108 100644 --- a/cash-api/order-server/src/main/resources/application.yml +++ b/cash-api/order-server/src/main/resources/application.yml @@ -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: diff --git a/cash-api/product-server/src/main/java/com/czg/ProductApplication.java b/cash-api/product-server/src/main/java/com/czg/ProductApplication.java index 2a249f206..e4591c188 100644 --- a/cash-api/product-server/src/main/java/com/czg/ProductApplication.java +++ b/cash-api/product-server/src/main/java/com/czg/ProductApplication.java @@ -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) { diff --git a/cash-api/product-server/src/main/resources/application.yml b/cash-api/product-server/src/main/resources/application.yml index e8fa88ffb..1fce90b04 100644 --- a/cash-api/product-server/src/main/resources/application.yml +++ b/cash-api/product-server/src/main/resources/application.yml @@ -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 diff --git a/cash-api/system-server/src/main/java/com/czg/SystemApplication.java b/cash-api/system-server/src/main/java/com/czg/SystemApplication.java index 5616ed785..e17607c4b 100644 --- a/cash-api/system-server/src/main/java/com/czg/SystemApplication.java +++ b/cash-api/system-server/src/main/java/com/czg/SystemApplication.java @@ -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) { diff --git a/cash-api/system-server/src/main/resources/application.yml b/cash-api/system-server/src/main/resources/application.yml index 3b3e1fd01..9774df2d5 100644 --- a/cash-api/system-server/src/main/resources/application.yml +++ b/cash-api/system-server/src/main/resources/application.yml @@ -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 diff --git a/cash-common/cash-common-service/src/main/java/com/czg/order/service/ShopOrderStatisticService.java b/cash-common/cash-common-service/src/main/java/com/czg/order/service/ShopOrderStatisticService.java index 25dbcec37..7cfef6516 100644 --- a/cash-common/cash-common-service/src/main/java/com/czg/order/service/ShopOrderStatisticService.java +++ b/cash-common/cash-common-service/src/main/java/com/czg/order/service/ShopOrderStatisticService.java @@ -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 * 获取支付方式数据 */ List getSummaryPayTypeData(Long shopId, Integer day); + /** + * 利润率折线图 + */ + List profitRateBarChart(Long shopId, Integer day); + + /** + * 成本折线图 + */ + List costLineChart(Long shopId, Integer day); + diff --git a/cash-common/cash-common-service/src/main/java/com/czg/order/vo/CostLineChartVO.java b/cash-common/cash-common-service/src/main/java/com/czg/order/vo/CostLineChartVO.java new file mode 100644 index 000000000..d0c858a89 --- /dev/null +++ b/cash-common/cash-common-service/src/main/java/com/czg/order/vo/CostLineChartVO.java @@ -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 mergeAndFillData(CostLineChartVO onlineData, List historyData, + LocalDate startDate, LocalDate endDate) { + // 创建日期到数据的映射,方便查找 + Map dataMap = new HashMap<>(); + + // 将历史数据放入映射 + for (CostLineChartVO vo : historyData) { + if (vo.getTradeDay() != null) { + dataMap.put(vo.getTradeDay(), vo); + } + } + dataMap.put(onlineData.getTradeDay(), onlineData); + + List 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; + } +} diff --git a/cash-common/cash-common-service/src/main/java/com/czg/order/vo/CountPayTypeVo.java b/cash-common/cash-common-service/src/main/java/com/czg/order/vo/CountPayTypeVo.java index 20dde894c..2d4172091 100644 --- a/cash-common/cash-common-service/src/main/java/com/czg/order/vo/CountPayTypeVo.java +++ b/cash-common/cash-common-service/src/main/java/com/czg/order/vo/CountPayTypeVo.java @@ -40,6 +40,21 @@ public class CountPayTypeVo { PAY_TYPE_MAPPING.put("creditPay", "挂账支付"); } + /** + * 实时数据 + */ + public static List realTimeDataByDay(Map realTimeData) { + List result = new ArrayList<>(); + for (Map.Entry 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; + } /** * 合并实时数据和历史统计数据 diff --git a/cash-common/cash-common-service/src/main/java/com/czg/order/vo/ProfitRateVO.java b/cash-common/cash-common-service/src/main/java/com/czg/order/vo/ProfitRateVO.java new file mode 100644 index 000000000..ca8c9cbef --- /dev/null +++ b/cash-common/cash-common-service/src/main/java/com/czg/order/vo/ProfitRateVO.java @@ -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 mergeAndFillData(ProfitRateVO onlineData, List historyData, + LocalDate startDate, LocalDate endDate) { + // 创建日期到数据的映射,方便查找 + Map dataMap = new HashMap<>(); + + // 将历史数据放入映射 + for (ProfitRateVO vo : historyData) { + if (vo.getTradeDay() != null) { + dataMap.put(vo.getTradeDay(), vo); + } + } + dataMap.put(onlineData.getTradeDay(), onlineData); + + List 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; + } +} diff --git a/cash-common/cash-common-tools/src/main/resources/application-tools.yml b/cash-common/cash-common-tools/src/main/resources/application-tools.yml deleted file mode 100644 index 14989e14a..000000000 --- a/cash-common/cash-common-tools/src/main/resources/application-tools.yml +++ /dev/null @@ -1,5 +0,0 @@ -alipay: - sms: - key: LTAI5tPdEfYSZcqHbjCrtPRD - secret: DZjyHBq3nTujF0NMLxnZgsecU8ZCvy - templateCode: SMS_244665149 \ No newline at end of file diff --git a/cash-service/order-service/src/main/java/com/czg/service/order/mapper/ShopOrderStatisticMapper.java b/cash-service/order-service/src/main/java/com/czg/service/order/mapper/ShopOrderStatisticMapper.java index d0d6fca9e..feba7705a 100644 --- a/cash-service/order-service/src/main/java/com/czg/service/order/mapper/ShopOrderStatisticMapper.java +++ b/cash-service/order-service/src/main/java/com/czg/service/order/mapper/ShopOrderStatisticMapper.java @@ -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 Map 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 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 costLineChart(Long shopId, LocalDate start, LocalDate end); + + //*********************以下为日常统计******************************************************************************** diff --git a/cash-service/order-service/src/main/java/com/czg/service/order/service/impl/ShopOrderStatisticServiceImpl.java b/cash-service/order-service/src/main/java/com/czg/service/order/service/impl/ShopOrderStatisticServiceImpl.java index 09e43696b..198759919 100644 --- a/cash-service/order-service/src/main/java/com/czg/service/order/service/impl/ShopOrderStatisticServiceImpl.java +++ b/cash-service/order-service/src/main/java/com/czg/service/order/service/impl/ShopOrderStatisticServiceImpl.java @@ -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 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 statDateRange = mapper.getStatDateRange(shopId, startDate, currentDate); - return TotalVo.mergeAndFillData(onlineDataAmount, statDateRange, startDate, currentDate); } @Override public List getSummaryPayTypeData(Long shopId, Integer day) { + LocalDate currentDate = LocalDate.now(); + LocalDate startDate; + if (day <= 1) { + Map 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 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 statDateRange = mapper.profitRateBarChart(shopId, startDate, currentDate); + return ProfitRateVO.mergeAndFillData(onlineProfitRateBarChart, statDateRange, startDate, currentDate); + } + + @Override + public List costLineChart(Long shopId, Integer day) { LocalDate currentDate = LocalDate.now(); LocalDate startDate = currentDate; if (day == 7) { @@ -89,11 +120,17 @@ public class ShopOrderStatisticServiceImpl extends ServiceImpl 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 0) { - BigDecimal profitRate = result.getProfitAmount().divide(result.getPayAmount(), 4, RoundingMode.HALF_DOWN).multiply(BigDecimal.valueOf(100)); - result.setProfitRate(profitRate); - } else { - result.setProfitRate(BigDecimal.ZERO); + profitRate = profitAmount.divide(result.getPayAmount(), 4, RoundingMode.HALF_DOWN) + .multiply(BigDecimal.valueOf(100)); } - //净利润 净利率 目前和 毛利润 毛利率 一致 - result.setNetProfitRate(result.getProfitRate()); - result.setNetProfitAmount(result.getProfitAmount()); - //客单价 实付金额(包括线上支付 包含现金支付 包含会员支付 包含挂账)/就餐人数 + result.setProfitRate(profitRate); + + // 净利润、净利率目前和毛利润、毛利率一致 + result.setNetProfitAmount(profitAmount); + result.setNetProfitRate(profitRate); + } + + /** + * 计算客单价 + * 客单价 = 实付金额 / 就餐人数(就餐人数为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); } + result.setTurnoverRate(turnoverRate); }