wzy 3 miesięcy temu
rodzic
commit
7292bc8bf5

+ 78 - 0
mjava-jiuan/pom.xml

@@ -0,0 +1,78 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.springframework.boot</groupId>
+        <artifactId>spring-boot-starter-parent</artifactId>
+        <version>2.2.0.RELEASE</version> <!-- 使用最新的稳定版或其他适用版本 -->
+        <relativePath/> <!-- lookup parent from repository -->
+    </parent>
+
+    <groupId>com.malk.jiuan</groupId>
+    <artifactId>mjava-jiuan</artifactId>
+
+    <properties>
+        <maven.compiler.source>8</maven.compiler.source>
+        <maven.compiler.target>8</maven.compiler.target>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-web</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-test</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>com.malk</groupId>
+            <artifactId>base</artifactId>
+            <version>1.1-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>easyexcel</artifactId>
+            <version>3.3.2</version>
+            <scope>compile</scope>
+        </dependency>
+        <dependency>
+            <groupId>com.squareup.okhttp3</groupId>
+            <artifactId>okhttp</artifactId>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <finalName>jiuan</finalName>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <version>3.1</version>
+                <configuration>
+                    <source>1.8</source>
+                    <target>1.8</target>
+                    <encoding>UTF-8</encoding>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-maven-plugin</artifactId>
+                <configuration>
+                    <executable>true</executable>
+                    <includeSystemScope>true</includeSystemScope>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>

+ 17 - 0
mjava-jiuan/src/main/java/com/malk/jiuan/JiuanApplication.java

@@ -0,0 +1,17 @@
+package com.malk.jiuan;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.scheduling.annotation.EnableScheduling;
+
+@SpringBootApplication(scanBasePackages = {"com.malk"})
+@EnableScheduling
+public class JiuanApplication {
+    public static void main(String[] args) {
+        try {
+            SpringApplication.run(JiuanApplication.class,args);
+        }catch (Exception e){
+            e.printStackTrace();
+        }
+    }
+}

+ 21 - 0
mjava-jiuan/src/main/java/com/malk/jiuan/controller/JiuanController.java

@@ -0,0 +1,21 @@
+package com.malk.jiuan.controller;
+
+import com.malk.jiuan.service.JiuanService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController
+public class JiuanController {
+
+    @Autowired
+    private JiuanService jiuanService;
+
+    //每日定时转换门店流水数据
+    @Scheduled(cron = "0 50 23 * * ?")
+    @GetMapping("/convertFile")
+    public void convertFile(){
+        jiuanService.convertFile();
+    }
+}

+ 18 - 0
mjava-jiuan/src/main/java/com/malk/jiuan/entity/ConvertSales.java

@@ -0,0 +1,18 @@
+package com.malk.jiuan.entity;
+
+import com.alibaba.excel.annotation.ExcelProperty;
+import lombok.Data;
+
+import java.util.Date;
+import java.util.List;
+
+@Data
+public class ConvertSales{
+    private String row1;//收银机号
+    private String row2;//交易流水号
+    private String row3;//支付时间
+    private String row4;//整单实收金额
+    private String row5;//货品编码
+    private String row6;//付款方式
+    private String row7;//备注
+}

+ 18 - 0
mjava-jiuan/src/main/java/com/malk/jiuan/entity/Sales.java

@@ -0,0 +1,18 @@
+package com.malk.jiuan.entity;
+
+import com.alibaba.excel.annotation.ExcelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.util.Date;
+
+@Data
+@EqualsAndHashCode
+public class Sales {
+    @ExcelProperty("支付时间")
+    private Date zfsj;//交易时间
+    @ExcelProperty("支付总额")
+    private Double zfze;//整单实收金额
+    @ExcelProperty("支付方式")
+    private String zffs;//付款方式
+}

+ 18 - 0
mjava-jiuan/src/main/java/com/malk/jiuan/entity/SalesReturn.java

@@ -0,0 +1,18 @@
+package com.malk.jiuan.entity;
+
+import com.alibaba.excel.annotation.ExcelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.util.Date;
+
+@Data
+@EqualsAndHashCode
+public class SalesReturn {
+    @ExcelProperty("退款时间")
+    private Date tksj;//交易时间
+    @ExcelProperty("应退总额")
+    private Double ytze;//整单实收金额
+    @ExcelProperty("支付方式")
+    private String zffs;//付款方式
+}

+ 5 - 0
mjava-jiuan/src/main/java/com/malk/jiuan/service/JiuanService.java

@@ -0,0 +1,5 @@
+package com.malk.jiuan.service;
+
+public interface JiuanService {
+    void convertFile();
+}

+ 250 - 0
mjava-jiuan/src/main/java/com/malk/jiuan/service/impl/JiuanServiceImpl.java

@@ -0,0 +1,250 @@
+package com.malk.jiuan.service.impl;
+
+import com.alibaba.excel.EasyExcel;
+import com.alibaba.excel.read.listener.PageReadListener;
+import com.alibaba.fastjson.JSON;
+import com.malk.jiuan.entity.ConvertSales;
+import com.malk.jiuan.entity.Sales;
+import com.malk.jiuan.entity.SalesReturn;
+import com.malk.jiuan.service.JiuanService;
+import com.malk.server.dingtalk.DDR_New;
+import com.malk.service.dingtalk.DDClient;
+import com.malk.utils.UtilHttp;
+import com.malk.utils.UtilMap;
+import lombok.extern.slf4j.Slf4j;
+import okhttp3.*;
+import okio.BufferedSink;
+import okio.Okio;
+import okio.Sink;
+import org.apache.logging.log4j.util.Strings;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Service;
+
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.lang.reflect.Field;
+import java.text.DecimalFormat;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.ZoneId;
+import java.time.format.DateTimeFormatter;
+import java.util.*;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.stream.Collectors;
+
+@Slf4j
+@Service
+public class JiuanServiceImpl implements JiuanService {
+    private final static String SHOP_NUMBER = "TJMP1F140";//商铺号
+    private final static String CASH_REGISTER_Number = "1400";//收银机号
+    private final static String GOODS_NUMBER = "00101701";//货品编码
+
+    private final static String DATE_PATTERN1 = "yyyy-MM-dd HH:mm:ss";
+    private final static String DATE_PATTERN2 = "yyyyMMddHHmmss";
+    private final static String DATE_PATTERN3 = "yyyyMMdd";
+
+    @Value(value = "${dingtalk.spaceId}")
+    private String SPACE_ID;
+
+    @Value(value = "${dingtalk.unionId}")
+    private String UNION_ID;
+
+    @Value(value = "${saveFile.path}")
+    private String saveFilePath;
+
+    @Autowired
+    private DDClient ddClient;
+
+
+    @Override
+    public void convertFile() {
+        // 获取当前时间
+        LocalDateTime now = LocalDateTime.now();
+        // 定义格式:yyyyMMddhhmmss
+        DateTimeFormatter formatter2 = DateTimeFormatter.ofPattern(DATE_PATTERN2);
+        // 定义格式:yyyyMMdd
+        DateTimeFormatter formatter3 = DateTimeFormatter.ofPattern(DATE_PATTERN3);
+        // 格式化时间
+        String formattedTime = now.format(formatter2);
+
+        String formattedTime3 = now.format(formatter3);
+
+        //搜索钉盘文件
+        Map query = new HashMap();
+        query.put("parentId",0);
+        query.put("unionId", UNION_ID);
+        query.put("maxResults",10);
+        query.put("orderBy","CREATE_TIME");
+        query.put("order","DESC");
+        DDR_New ddrNew = (DDR_New) UtilHttp.doGet("https://api.dingtalk.com/v1.0/storage/spaces/" + SPACE_ID + "/dentries", ddClient.initTokenHeader(), query, DDR_New.class);
+
+        List<Map> dentries = ddrNew.getDentries();
+
+        String fileId = "";
+        String fileName = "";
+
+        for (Map dentry : dentries) {
+            String name = UtilMap.getString(dentry, "name");
+            if (name.contains(formattedTime3)) {
+                fileId = UtilMap.getString(dentry, "id");
+                fileName = name;
+                break;
+            }
+        }
+
+        //获取文件下载信息
+        query.keySet().removeIf(key -> !key.equals("unionId"));
+        DDR_New ddrNew2 = (DDR_New) UtilHttp.doPost("https://api.dingtalk.com/v1.0/storage/spaces/" + SPACE_ID + "/dentries/" + fileId + "/downloadInfos/query", ddClient.initTokenHeader(), query, null,DDR_New.class);
+
+        Map headerSignatureInfo = ddrNew2.getHeaderSignatureInfo();
+
+        Map<String,String> headers = UtilMap.getMap(headerSignatureInfo, "headers");
+
+        List<String> resourceUrls = UtilMap.getList(headerSignatureInfo, "resourceUrls");
+
+        downloadDdFile(resourceUrls.get(0) ,headers, saveFilePath + fileName);
+
+        List<Sales> salesList = new ArrayList<>();
+
+        //销售单
+        EasyExcel.read(saveFilePath + fileName, Sales.class, new PageReadListener<Sales>(dataList -> {
+            for (Sales Sales : dataList) {
+                log.info("读取到一条数据{}", JSON.toJSONString(Sales));
+                salesList.add(Sales);
+            }
+        })).sheet(0).doRead();
+
+        //退货单
+        EasyExcel.read(saveFilePath + fileName, SalesReturn.class, new PageReadListener<SalesReturn>(dataList -> {
+            for (SalesReturn salesReturn : dataList) {
+                log.info("读取到一条数据{}", JSON.toJSONString(salesReturn));
+                Sales sales = new Sales();
+                sales.setZfze(salesReturn.getYtze());//应退金额
+                sales.setZfsj(salesReturn.getTksj());//退款时间
+                sales.setZffs(salesReturn.getZffs());//支付方式
+                salesList.add(sales);
+            }
+        })).sheet(1).doRead();
+
+        //支付时间升序
+        List<Sales> sortedSalesList = salesList.stream()
+                .sorted(Comparator.comparing(Sales::getZfsj))
+                .collect(Collectors.toList());
+
+        AtomicInteger counter = new AtomicInteger(1);
+        String currentDatePrefix = "";
+
+        List<ConvertSales> convertSalesList = new ArrayList<>();
+
+        for (Sales sales : sortedSalesList) {
+            // 获取日期的YYMMDD部分
+            LocalDate date = sales.getZfsj().toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
+            LocalDateTime localDateTime = sales.getZfsj().toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
+
+            String datePrefix = date.format(DateTimeFormatter.ofPattern("yyMMdd"));
+
+            // 如果日期变化,重置计数器
+            if (!datePrefix.equals(currentDatePrefix)) {
+                currentDatePrefix = datePrefix;
+                counter.set(1);
+            }
+
+            // 生成流水号:YYMMDD + 4位流水(不足补零)
+            String serialNumber = String.format("%s%04d", datePrefix, counter.getAndIncrement());
+
+            ConvertSales convertSales = new ConvertSales();
+
+            convertSales.setRow1(CASH_REGISTER_Number);//收银机号
+
+            convertSales.setRow2(serialNumber);//交易流水号
+
+            convertSales.setRow3(localDateTime.format(DateTimeFormatter.ofPattern(DATE_PATTERN1)));//支付时间
+
+            convertSales.setRow4(new DecimalFormat("0.00").format(sales.getZfze()));//整单实收金额
+
+            convertSales.setRow5(GOODS_NUMBER);//货品编号
+
+            //交易方式
+            if (Strings.isNotBlank(sales.getZffs())){
+                switch (sales.getZffs()){
+                    case "现金支付" : convertSales.setRow6("01");break;
+                    case "其他" : convertSales.setRow6("06");break;
+                    /*case "刷卡支付" : convertSales.setRow6("02");break;
+                    case "外挂POS机" : convertSales.setRow6("03");break;
+                    case "储值卡" : convertSales.setRow6("04");break;
+                    case "代金卷" : convertSales.setRow6("05");break;*/
+                    default: convertSales.setRow6("03");break;//外挂pos机
+                }
+            }
+
+            convertSalesList.add(convertSales);
+        }
+
+        // 将对象列表写入文件
+
+
+        String newFileName = SHOP_NUMBER + "_" + formattedTime + "_LIST.txt";
+//        String newFileName = SHOP_NUMBER + "_" + "20250819235959" + "_LIST.txt";
+        writeObjectsToFile(convertSalesList, "d:\\" + newFileName);
+    }
+
+    /**
+     *
+     * @param url 调用获取下载信息接口获取的internalResourceUrls
+     * @param path 文件要下载的目标路径
+     * @param headers 调用下载信息接口获取的headers
+     */
+    public static void downloadDdFile(String url,Map<String,String> headers,String path){
+        OkHttpClient client = new OkHttpClient();
+        Request request = new Request.Builder()
+                .url(url)
+                .headers(Headers.of(headers))
+                .build();
+        try (Response response = client.newCall(request).execute()) { // 同步请求
+            if (!response.isSuccessful()) {
+                throw new IOException("服务器返回错误: " + response.code());
+            }
+            File dest = new File(path);
+            try (BufferedSink sink = Okio.buffer(Okio.sink(dest))) {
+                sink.writeAll(response.body().source());
+                System.out.println("文件下载成功: " + dest.getAbsolutePath());
+            }
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    public static <T> void writeObjectsToFile(List<T> objects, String filePath) {
+        try (BufferedWriter writer = new BufferedWriter(new FileWriter(filePath))) {
+            if (objects == null || objects.size() == 0) {
+                return;
+            }
+
+            // 获取对象的所有字段(包括私有字段)
+            Field[] fields = objects.get(0).getClass().getDeclaredFields();
+
+            // 遍历对象数组
+            for (T obj : objects) {
+                StringBuilder line = new StringBuilder();
+
+                // 遍历每个字段
+                for (Field field : fields) {
+                    field.setAccessible(true); // 允许访问私有字段
+                    Object value = field.get(obj);
+                    line.append(value != null ? value.toString() : "").append(",");
+                }
+
+                // 写入行(以逗号结尾后换行)
+                writer.write(line.toString());
+                writer.newLine();
+            }
+
+            System.out.println("数据已成功写入文件: " + filePath);
+        } catch (IOException | IllegalAccessException e) {
+            System.err.println("写入文件时出错: " + e.getMessage());
+        }
+    }
+}

+ 28 - 0
mjava-jiuan/src/main/resources/application-dev.yml

@@ -0,0 +1,28 @@
+server:
+  port: 9033
+  servlet:
+    context-path: /jiuan
+
+enable:
+  scheduling: false
+logging:
+  config: classpath:logback-spring.xml
+  path: /home/server/jiuan/log/
+  level:
+    com.malk.*: debug
+
+# dingtalk
+dingtalk:
+  agentId: 3749205961
+  appKey: dingdcxnvojhmwi1lau0
+  appSecret: K0dfunjkLVQKzEN6KXbjdUxcVAX5_hyc0rTNzrj4MugXKc-dkn0erpAxzhSeGPVC
+  corpId:
+  aesKey:
+  token:
+  operator: 344749020127590108 #wzy
+  unionId: 78gv4v47UXQyu5fYF78VGgiEiE #wzy
+  spaceId: 27116618877 #钉盘-团队文件-门店数据
+
+saveFile:
+  path: d:\\
+

+ 35 - 0
mjava-jiuan/src/main/resources/application-prod.yml

@@ -0,0 +1,35 @@
+#测试学习
+server:
+  port: 9033
+  servlet:
+    context-path: /jiuan
+
+enable:
+  scheduling: false
+logging:
+  config: classpath:logback-spring.xml
+  path: d:\\jiuan\log\
+  level:
+    com.malk.*: info
+
+# dingtalk
+dingtalk:
+  agentId: 3749205961
+  appKey: dingdcxnvojhmwi1lau0
+  appSecret: K0dfunjkLVQKzEN6KXbjdUxcVAX5_hyc0rTNzrj4MugXKc-dkn0erpAxzhSeGPVC
+  corpId:
+  aesKey:
+  token:
+  operator: 1656315499790273 #孙海生
+  unionId: iPPoZ001WAYlZxyoU04g2bgiEiE #孙海生
+  spaceId: 26395140381 #钉盘-团队文件-宜搭文件库
+  partnersDentryId: 176651024213 #钉盘-团队文件-宜搭文件库-合作伙伴文件
+  unrestrictedDonationDentryId: 176648777099 #钉盘-团队文件-宜搭文件库-资助人费用登记文件
+
+aliwork:
+  appType: APP_TTZS5KICGVVQNZ3RS8T4
+  systemToken: DWF66OA1K1VTVWET83C0SD6RULBO31AQEYG8MQO
+
+saveFile:
+  path: /home/server/lianxiang/file/
+

+ 61 - 0
mjava-jiuan/src/main/resources/logback-spring.xml

@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<configuration debug="false" scan="false" scanPeriod="60 seconds">
+    <springProperty scope="context" name="LOG_HOME" source="logging.path" defaultValue="/home/server/log/"/>
+    <property name="FileNamePattern" value="${LOG_HOME}%d{yyyyMM}/%d{dd}"/>
+
+    <!-- 定义控制台输出 -->
+    <appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
+        <layout class="ch.qos.logback.classic.PatternLayout">
+            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} - [%thread] - %-5level - %logger{50} - %msg%n</pattern>
+        </layout>
+    </appender>
+
+    <appender name="appLogAppender" class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <!-- 指定日志文件的名称 -->
+        <!--<file>${FileNamePattern}/info.log</file>-->
+
+        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+            <fileNamePattern>${FileNamePattern}/info-%i.log</fileNamePattern>
+            <MaxHistory>30</MaxHistory>
+            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
+                <MaxFileSize>30MB</MaxFileSize>
+            </timeBasedFileNamingAndTriggeringPolicy>
+        </rollingPolicy>
+
+        <layout class="ch.qos.logback.classic.PatternLayout">
+            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [ %thread ] - [ %-5level ] [ %logger{50} : %line ] - %msg%n</pattern>
+        </layout>
+    </appender>
+
+    <appender name="SIFT" class="ch.qos.logback.classic.sift.SiftingAppender">
+        <discriminator>
+            <Key>processid</Key>
+            <DefaultValue>sys</DefaultValue>
+        </discriminator>
+        <sift>
+            <appender name="FILE-${processid}"
+                      class="ch.qos.logback.core.rolling.RollingFileAppender">
+                <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+                    <FileNamePattern>
+                        ${FileNamePattern}/${processid}.log
+                    </FileNamePattern>
+                </rollingPolicy>
+                <layout class="ch.qos.logback.classic.PatternLayout">
+                    <Pattern>
+                        %d{yyyyMMdd:HH:mm:ss.SSS} [%thread] %-5level %msg%n
+                    </Pattern>
+                </layout>
+            </appender>
+        </sift>
+    </appender>
+
+
+    <!-- 日志输出级别 -->
+    <logger name="org.springframework" level="debug"  additivity="false"/>
+    <logger name="com.malk.connecter" level="debug"/>
+    <root level="INFO">
+        <appender-ref ref="stdout"/>
+        <appender-ref ref="appLogAppender"/>
+        <appender-ref ref="SIFT"/>
+    </root>
+</configuration>

+ 21 - 0
mjava-jiuan/src/test/java/com/malk/jiuan/JiuanTest.java

@@ -0,0 +1,21 @@
+package com.malk.jiuan;
+
+import com.malk.jiuan.service.JiuanService;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringRunner;
+
+@SpringBootTest
+@RunWith(SpringRunner.class)
+public class JiuanTest {
+
+    @Autowired
+    private JiuanService jiuanService;
+
+    @Test
+    public void test(){
+        jiuanService.convertFile();
+    }
+}