feat(home): 添加报表日期范围筛选功能并完善设备维护管理
- 在HomeController中为多个报表接口添加开始和结束日期参数支持
- 实现HomeService中各类报表方法的日期范围查询逻辑
- 添加设备维护完成和批量完成功能接口及实现
- 完善DeviceMaintenanceDto中添加日期分组字段
- 优化DeviceMaintenanceMapper查询结果按创建时间倒序排列
- 新增增值税明细按发票/订单展示接口
- 实现巡检任务完成和批量完成功能
- 更新相关实体类和映射文件以支持新功能
- 修改开发环境端口配置从7006调整为7005
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | # /æ°æ®åºè¿ç§» |
| | | |
| | | å¨è¿è¡**æ°æ®åºè¿ç§»**æ¶ä½¿ç¨æ¤å·¥ä½æµã |
| | | |
| | | ## ç®æ |
| | | |
| | | å®å
¨çæ°æ®åºè¿ç§»å·¥ä½æµ |
| | | |
| | | ## å¸¸ç¨æä»¶ |
| | | |
| | | - `migrations/*` |
| | | - `schemas/*` |
| | | - `**/models/**` |
| | | - `**/db/**` |
| | | |
| | | ## 建议æ¥éª¤ |
| | | |
| | | 1. æ¥çç°æè¿ç§»ä»¥äºè§£æ¨¡å¼ã |
| | | 2. åå»ºå¸¦ææ¶é´æ³åç¼çæ°è¿ç§»æä»¶ã |
| | | 3. ç¼åæ¯æåæ»çè¿ç§»ã |
| | | 4. 卿¬å°ç¯å¢ä¸æµè¯è¿ç§»ã |
| | | 5. è®°å½ä»»ä½ç ´åæ§åæ´ã |
| | | |
| | | ## å
¸åæäº¤ä¿¡æ¯ |
| | | |
| | | - 为[åè½]æ·»å è¿ç§» |
| | | - ä¿®å¤è¿ç§»[æè¿°] |
| | | - æ´æ°æ¶æææ¡£ |
| | | |
| | | ## 注æäºé¡¹ |
| | | |
| | | - å§ç»å¨å¯æ¬ä¸æµè¯è¿ç§»ã |
| | | - ç¡®ä¿åæ»èæ¬ä¹ç»è¿æµè¯ã |
| | | - 没æå¤ä»½çæ
åµä¸é¿å
ç ´åæ§æä½ã |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | # /åè½å¼å |
| | | |
| | | å¨è¿è¡**åè½å¼å**æ¶ä½¿ç¨æ¤å·¥ä½æµã |
| | | |
| | | ## ç®æ |
| | | |
| | | æ åååè½å®ç°å·¥ä½æµ |
| | | |
| | | ## å¸¸ç¨æä»¶ |
| | | |
| | | - `manifests/*` |
| | | - `schemas/*` |
| | | - `**/*.test.*` |
| | | - `**/api/**` |
| | | |
| | | ## 建议æ¥éª¤ |
| | | |
| | | 1. å¨ç¼è¾åäºè§£å½åç¶æå失败模å¼ã |
| | | 2. è¿è¡æå°ä¸è¿è´¯çæ´æ¹ä»¥æ»¡è¶³å·¥ä½æµç®æ ã |
| | | 3. 对修æ¹çæä»¶è¿è¡æç¸å
³çéªè¯ã |
| | | 4. æ»ç»æ´æ¹å
容以åä»é审æ¥çé¨åã |
| | | |
| | | ## å
¸åæäº¤ä¿¡æ¯ |
| | | |
| | | - æ·»å åè½å®ç° |
| | | - 为åè½æ·»å æµè¯ |
| | | - æ´æ°ææ¡£ |
| | | |
| | | ## 注æäºé¡¹ |
| | | |
| | | - å°æ¤è§ä¸ºèææ¶ï¼èé硬ç¼ç èæ¬ã |
| | | - 妿工使µæé大ååï¼æ´æ°æ¤å½ä»¤ã |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | { |
| | | "name": "product-inventory-management", |
| | | "description": "Product inventory management system with JDK 25+", |
| | | "language": "Java", |
| | | "framework": "Spring Boot", |
| | | "database": "MySQL", |
| | | "orm": "MyBatis", |
| | | "javaVersion": "25" |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | # æ¥å£åæ´åç«¯ææ¡£è§å |
| | | |
| | | ## è§å |
| | | |
| | | - æ¯æ¬¡æ¶åæ¥å£åæ´ï¼æ°å¢æ¥å£ãä¿®æ¹è¯·æ±åæ°ãä¿®æ¹ååºç»æï¼æ¶ï¼å¿
é¡»è¾åºä¸ä»½åç«¯ä¿®æ¹ææ¡£å° `docs/` ç®å½ã |
| | | - ææ¡£ä»¥ Markdown æ ¼å¼ç¼åï¼æä»¶å使ç¨å°å忝åä¸å线ï¼å¦ `docs/customer_handover.md`ã |
| | | - ææ¡£å
容è³å°å
å«ï¼API 说æï¼è·¯å¾ãæ¹æ³ã请æ±åæ°ãååºæ ¼å¼ï¼ãæ¶åçå端页é¢ãå
·ä½çä¿®æ¹ä»£ç 示ä¾ã |
| | | |
| | | ## ææ¡£æ¨¡æ¿ |
| | | |
| | | ```markdown |
| | | # åè½åç§° |
| | | |
| | | ## æ¶åé¡µé¢ |
| | | |
| | | - 页é¢1 |
| | | - 页é¢2 |
| | | |
| | | ## API |
| | | |
| | | | æ¹æ³ | è·¯å¾ | 说æ | |
| | | |------|------|------| |
| | | | POST | /xxx/xxx | 说æ | |
| | | |
| | | **请æ±åæ°ï¼** |
| | | |
| | | | åæ° | ç±»å | å¿
å¡« | 说æ | |
| | | |------|------|------|------| |
| | | | xxx | String | æ¯ | xxx | |
| | | |
| | | **ååºï¼** `{ "code": 200, "msg": "æä½æå" }` |
| | | |
| | | ## å端修æ¹ç¹ |
| | | |
| | | ### 1. æé®/å¼¹çª/è¡¨æ ¼ç |
| | | |
| | | \`\`\`html |
| | | <el-button>xxx</el-button> |
| | | \`\`\` |
| | | |
| | | ### 2. data æ°æ® |
| | | |
| | | \`\`\`js |
| | | data() { |
| | | return { |
| | | xxx: '', |
| | | } |
| | | } |
| | | \`\`\` |
| | | |
| | | ### 3. æ¹æ³ |
| | | |
| | | \`\`\`js |
| | | handleXxx() { |
| | | // ... |
| | | } |
| | | \`\`\` |
| | | |
| | | ## 注æäºé¡¹ |
| | | |
| | | - 注æäºé¡¹1 |
| | | - 注æäºé¡¹2 |
| | | ``` |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | # å®å
¨æ¤æ |
| | | |
| | | ## SQL 注å
¥é²æ¤ |
| | | |
| | | - æ°¸è¿ä¸è¦å°ç¨æ·è¾å
¥ç´æ¥æ¼æ¥å° SQL æ¥è¯¢ä¸ã |
| | | - å§ç»ä½¿ç¨åæ°åæ¥è¯¢æ ORM æ¹æ³ã |
| | | - 卿°æ®åºæä½åéªè¯åæ¸
çææè¾å
¥ã |
| | | |
| | | ## XSS 鲿¤ |
| | | |
| | | - å¨ HTML 䏿¸²æåè½¬ä¹ææç¨æ·çæçå
容ã |
| | | - ä½¿ç¨æ¨¡æ¿èªå¨è½¬ä¹åè½ã |
| | | - å¨å®¢æ·ç«¯åæå¡å¨ç«¯é½è¿è¡è¾å
¥éªè¯åæ¸
çã |
| | | |
| | | ## å¯é¥ç®¡ç |
| | | |
| | | - æ°¸è¿ä¸è¦å¨æºä»£ç ä¸ç¡¬ç¼ç å¯é¥ãAPI å¯é¥æå¯ç ã |
| | | - 使ç¨ç¯å¢åéæå®å
¨ä¿é©åºåå¨æææ°æ®ã |
| | | - å®æè½®æ¢å¯é¥ï¼é¿å
卿¥å¿ä¸è®°å½å®ä»¬ã |
| | | |
| | | ## è¾å
¥éªè¯ |
| | | |
| | | - å¨ç³»ç»è¾¹çå¤éªè¯ææè¾å
¥ã |
| | | - 使ç¨ç½ååèéé»ååè¿è¡éªè¯ã |
| | | - å¨å¤çä¸ä¼ åæ£æ¥æä»¶ç±»åå大å°ã |
| | | |
| | | ## é误å¤ç |
| | | |
| | | - ä¸è¦å¨éè¯¯æ¶æ¯ä¸æ´é²ææä¿¡æ¯ã |
| | | - å¨å
é¨è®°å½è¯¦ç»é误ï¼åç¨æ·è¿åéç¨æ¶æ¯ã |
| | | - å¤çææå¼å¸¸ä»¥é²æ¢ä¿¡æ¯æ³é²ã |
| | | |
| | | ## ä¾èµç®¡ç |
| | | |
| | | - ä¿æä¾èµé¡¹æ´æ°ã |
| | | - 审计ä¾èµé¡¹ä¸çå·²ç¥æ¼æ´ã |
| | | - åºå®çæ¬ä»¥é¿å
æå¤çç ´åæ§åæ´ã |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | { |
| | | "permissions": { |
| | | "allow": [ |
| | | "Read", |
| | | "Glob", |
| | | "Grep", |
| | | "Write", |
| | | "Edit", |
| | | "Bash(git status)", |
| | | "Bash(git diff)", |
| | | "Bash(npm test)", |
| | | "Bash(npm run build)", |
| | | "Bash(pytest *)", |
| | | "mcp__ide__getDiagnostics", |
| | | "Bash(mvn compile *)", |
| | | "Bash(sed -i '269,271d' src/main/resources/mapper/system/SysUserMapper.xml)", |
| | | "Bash(sed -i '268a\\\\\\\\t\\\\t<update id=\"resetAllUserPwd\">\\\\n\\\\t\\\\t\\\\tupdate sys_user set password = #{password} where del_flag = '\\\\''0'\\\\''\\\\n\\\\t\\\\t</update>' src/main/resources/mapper/system/SysUserMapper.xml)", |
| | | "Bash(sed -i '269s/^.*$/\\\\t\\\\t<update id=\"resetAllUserPwd\">/' src/main/resources/mapper/system/SysUserMapper.xml)", |
| | | "Bash(sed -i '270s/^.*$/\\\\t\\\\t\\\\tupdate sys_user set password = #{password} where del_flag = '\\\\''0'\\\\''/' src/main/resources/mapper/system/SysUserMapper.xml)", |
| | | "Bash(sed -i '271s/^.*$/\\\\t\\\\t<\\\\/update>/' src/main/resources/mapper/system/SysUserMapper.xml)" |
| | | ], |
| | | "deny": [ |
| | | "Bash(rm -rf *)", |
| | | "Bash(curl * | bash)", |
| | | "Bash(git push --force *)", |
| | | "Bash(sudo *)" |
| | | ] |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | # 项ç®å¼åçº¦å® |
| | | |
| | | ## æ¦è¿° |
| | | |
| | | æ¤æè½å®ä¹äºæ¬é¡¹ç®çå¼å模å¼å约å®ã |
| | | |
| | | ## ææ¯æ |
| | | |
| | | - **主è¦è¯è¨**: Java (JDK 25+) |
| | | - **æ¶æ**: Spring Boot + MyBatis |
| | | - **æµè¯ä½ç½®**: `src/test/java` |
| | | |
| | | ## æäº¤çº¦å® |
| | | |
| | | éµå¾ªçº¦å®å¼æäº¤æ ¼å¼ï¼ |
| | | |
| | | ### 使ç¨çåç¼ |
| | | |
| | | - `feat` - æ°åè½ |
| | | - `fix` - éè¯¯ä¿®å¤ |
| | | - `docs` - ææ¡£åæ´ |
| | | - `test` - æµè¯æ·»å ææ´æ° |
| | | - `refactor` - 代ç éæ |
| | | - `style` - 代ç 飿 ¼åæ´ï¼æ ¼å¼åãåå·çï¼ |
| | | - `chore` - æå»ºè¿ç¨æè¾
å©å·¥å
·åæ´ |
| | | |
| | | ### æ¶æ¯è§è |
| | | |
| | | - ä¿æç¬¬ä¸è¡ç®æ´ä¸ææè¿°æ§ï¼å°äº 70 个åç¬¦ï¼ |
| | | - 使ç¨ç¥ä½¿è¯æ°ï¼"æ·»å åè½"èé"æ·»å äºåè½"ï¼ |
| | | - ç¸å
³æ¶å
å«èå´ï¼`feat(èå´): æè¿°` |
| | | |
| | | ## 代ç 飿 ¼ |
| | | |
| | | - éµå¾ª Java å½åçº¦å® |
| | | - ä½¿ç¨ææä¹çåéåæ¹æ³å |
| | | - 为å
Œ
± API æ·»å Javadoc |
| | | - ä¿ææ¹æ³ä¸æ³¨ä¸åä¸èè´£ |
| | | |
| | | ## æµè¯ |
| | | |
| | | - 为ä¸å¡é»è¾ç¼ååå
æµè¯ |
| | | - ä¸ºæ°æ®åºæä½ä½¿ç¨éææµè¯ |
| | | - ä¿ææµè¯è¦ççå¨ 80% ä»¥ä¸ |
| | | |
| | | ## å并请æ±è§è |
| | | |
| | | - ä¿æå并请æ±ä¸æ³¨ä¸å° |
| | | - 为æ°åè½å
嫿µè¯ |
| | | - æ ¹æ®éè¦æ´æ°ææ¡£ |
| | | - åå¹¶å审æ¥ä»£ç |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | -- inspection_task 表æ°å¢ status åæ®µ |
| | | ALTER TABLE inspection_task ADD COLUMN status TINYINT DEFAULT 0 COMMENT 'ç¶æ 0å¾
å·¡æ£ 1已宿'; |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | # ä¸ã设å¤ç®¡ç模å |
| | | |
| | | ## 1\. å¤ä»¶ç®¡ç - å¤ä»¶é¢ç¨è®°å½ |
| | | |
| | | ç°æå¤ä»¶åºåºä»
è½ä¾æè®¾å¤æ£ä¿®åºæ¯ï¼åºåºæ¸ éåå¨å±éï¼éæ°å¢ç¬ç«å¤ä»¶åºåºåè½å
¥å£ï¼æ¯æç´æ¥å®æå¤ä»¶é¢ç¨åºåºæä½ã |
| | | |
| | | ## å¤ä»¶é¢ç¨è®°å½é¡µé¢2. 设å¤ä¿å
» - ä¿å
»ä»»å¡ |
| | | |
| | | ä¿å
»ä»»å¡ä¸ååï¼é¡µé¢åç
§éå® / éè´è®¢åæ ·å¼ï¼æ¯æææ¥æåç»æå å±ç¤ºï¼åç»æ¡ç®å¯å±å¼æ¥çæç»ï¼åæ¡æç»è¡æ«å°¾å¢å ãä¿å
»å®æãæä½æé®ï¼å¯åç¬åç»åæ¡ä¿å
»ä»»å¡ï¼æå æ±æ»ç¶æä¸ï¼æ°å¢ãä¸é®ä¿å
»å®æãæ¹éæä½æé®ï¼å¿«éåç»å½ååç»å
¨é¨ä¿å
»é¡¹ã |
| | | |
| | | ## ä¿å
»ä»»å¡é¡µé¢3. 设å¤å·¡æ£ - å·¡æ£ä»»å¡ |
| | | |
| | | å·¡æ£ä»»å¡ä¸å宿åï¼é¡µé¢åç
§éå® / éè´è®¢åå¸å±ï¼ææ¥æåç»æå å±ç¤ºï¼åç»æ¯æå±å¼æ¥çæç»ï¼æ¯æ¡å·¡æ£æç»åå¢è®¾ãå·¡æ£å®æãæé®ï¼æ¯æåç¬åç»åæ¡å·¡æ£è®°å½ï¼åç»æå æªå±å¼ç¶æä¸ï¼æä¾ãä¸é®å·¡æ£å®æãæ¹éæä½ï¼ç»ä¸åç»è¯¥åç»ä¸ææå·¡æ£ä»»å¡ã |
| | | |
| | | # äºãå³çåææ¨¡å |
| | | |
| | | ## 1\. å¢å¼ç¨å¯¹æ¯é¡µé¢ |
| | | |
| | | å½å页颿¥è¯¢æ æ°æ®ï¼æççè¦æ±ä¼åæ°æ®å±ç¤ºé»è¾ï¼å表å±ç¤ºå订åå¢å¼ç¨æç»ï¼é¡µé¢å³ä¾§æ°å¢æ±ç¶å¯è§åå¾è¡¨ï¼ç´è§å¯¹æ¯è¿é项å¢å¼ç¨æ°æ®ã |
| | | |
| | | ## å¢å¼ç¨å¯¹æ¯é¡µé¢2. 管ç驾驶è±ï¼PSI æ°æ®åæå¤§å±ï¼ |
| | | |
| | | ææ ä¿®æ¹ï¼å°é¡¶é¨ãéå®äº§åæ°ãè°æ´ä¸ºãéå®è®¢åæ°ãï¼æ¶é´çéï¼é¡µé¢å·¦ä¸è§æ°å¢æ¥æèå´ä¸æçéæ§ä»¶ï¼ææç»è®¡ææ æ æ³¨å½åçéæ¶æ®µï¼æ°æ®ä¿®å¤ï¼è§£å³ãéè´ååå¸ãç¯å½¢å¾æ æ°æ®å±ç¤ºé®é¢ã |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | # 管ç驾驶è±ï¼PSI æ°æ®åæå¤§å±ï¼ä¼å |
| | | |
| | | ## æ¶åé¡µé¢ |
| | | |
| | | - 管çé©¾é©¶è± / PSI æ°æ®åæå¤§å± |
| | | |
| | | ## API |
| | | |
| | | | æ¹æ³ | è·¯å¾ | 说æ | |
| | | |------|------|------| |
| | | | GET | /home/salesPurchaseStorageProductCount | éå®-éè´-å¨åç»è®¡ï¼æ°å¢æ¥æçéï¼ | |
| | | | GET | /home/productCategoryDistribution | 产å大类åå¸ï¼ä¿®å¤æ°æ®ï¼ | |
| | | |
| | | ### 1. éå®-éè´-å¨åç»è®¡æ¥å£ |
| | | |
| | | **请æ±åæ°ï¼æ°å¢ï¼ï¼** |
| | | |
| | | | åæ° | ç±»å | å¿
å¡« | 说æ | |
| | | |------|------|------|------| |
| | | | startDate | String | å¦ | å¼å§æ¥æï¼yyyy-MM-ddï¼ | |
| | | | endDate | String | å¦ | ç»ææ¥æï¼yyyy-MM-ddï¼ | |
| | | |
| | | ä¸ä¼ æ¥æåæ°æ¶é»è®¤ç»è®¡å½åæ vs 䏿ã |
| | | |
| | | **ååºæ ¼å¼ååï¼** |
| | | - 第ä¸ä¸ªææ åç§°ä» `"éå®äº§åæ°"` æ¹ä¸º `"éå®è®¢åæ°"` |
| | | - æ°å¼ç»è®¡å£å¾ä»"éå®äº§åè®°å½æ°"æ¹ä¸º"éå®è®¢åæ°ï¼sales_ledger è¡¨è®°å½æ°ï¼" |
| | | |
| | | ```json |
| | | { |
| | | "code": 200, |
| | | "data": [ |
| | | { "name": "éå®è®¢åæ°", "value": "156", "rate": "12.50" }, |
| | | { "name": "éè´äº§åæ°", "value": "89", "rate": "-5.30" }, |
| | | { "name": "å¨åäº§åæ°", "value": "234", "rate": "8.20" } |
| | | ] |
| | | } |
| | | ``` |
| | | |
| | | ### 2. 产å大类å叿¥å£ |
| | | |
| | | ä¿®å¤äºå°ç±» value/rate æ°æ®ä¸º 0 çé®é¢ï¼ç°å¨è¿åå®é
çéè´æ°æ®ã |
| | | |
| | | **ååºæ ¼å¼ï¼** |
| | | ```json |
| | | { |
| | | "code": 200, |
| | | "data": { |
| | | "items": [ |
| | | { |
| | | "name": "åææ", |
| | | "value": "45", |
| | | "rate": "40.50", |
| | | "children": [ |
| | | { "name": "颿", "value": "20", "rate": "44.44", "children": [] }, |
| | | { "name": "塿", "value": "15", "rate": "33.33", "children": [] }, |
| | | { "name": "çµåå
ä»¶", "value": "10", "rate": "22.22", "children": [] } |
| | | ] |
| | | } |
| | | ] |
| | | } |
| | | } |
| | | ``` |
| | | |
| | | ## å端修æ¹ç¹ |
| | | |
| | | ### 1. 顶鍿æ ä¿®æ¹ - "éå®äº§åæ°" â "éå®è®¢åæ°" |
| | | |
| | | ```html |
| | | <div class="stat-card"> |
| | | <div class="stat-label">éå®è®¢åæ°</div> |
| | | <div class="stat-value">{{ salesOrderCount.value }}</div> |
| | | <div class="stat-rate" :class="{ up: salesOrderCount.rate > 0, down: salesOrderCount.rate < 0 }"> |
| | | ç¯æ¯ {{ salesOrderCount.rate }}% |
| | | </div> |
| | | </div> |
| | | ``` |
| | | |
| | | ### 2. æ¥æèå´çéæ§ä»¶ |
| | | |
| | | å¨é¡µé¢å·¦ä¸è§æ°å¢æ¥æèå´ä¸æçéã |
| | | |
| | | ```html |
| | | <el-date-picker |
| | | v-model="dateRange" |
| | | type="daterange" |
| | | range-separator="è³" |
| | | start-placeholder="å¼å§æ¥æ" |
| | | end-placeholder="ç»ææ¥æ" |
| | | value-format="yyyy-MM-dd" |
| | | @change="handleDateChange" |
| | | style="margin-right: 16px;" /> |
| | | ``` |
| | | |
| | | ### 3. data æ°æ® |
| | | |
| | | ```js |
| | | data() { |
| | | return { |
| | | dateRange: [], |
| | | salesOrderCount: { value: 0, rate: 0 }, |
| | | purchaseProductCount: { value: 0, rate: 0 }, |
| | | storageProductCount: { value: 0, rate: 0 }, |
| | | productCategoryData: [], |
| | | } |
| | | } |
| | | ``` |
| | | |
| | | ### 4. æ¹æ³ |
| | | |
| | | ```js |
| | | async loadSalesPurchaseStorageCount() { |
| | | const params = {}; |
| | | if (this.dateRange && this.dateRange.length === 2) { |
| | | params.startDate = this.dateRange[0]; |
| | | params.endDate = this.dateRange[1]; |
| | | } |
| | | const res = await this.$http.get('/home/salesPurchaseStorageProductCount', { params }); |
| | | const data = res.data || []; |
| | | this.salesOrderCount = this.extractStatData(data[0]); |
| | | this.purchaseProductCount = this.extractStatData(data[1]); |
| | | this.storageProductCount = this.extractStatData(data[2]); |
| | | }, |
| | | |
| | | extractStatData(item) { |
| | | return item ? { |
| | | value: parseInt(item.value) || 0, |
| | | rate: parseFloat(item.rate) || 0, |
| | | } : { value: 0, rate: 0 }; |
| | | }, |
| | | |
| | | handleDateChange(val) { |
| | | this.loadSalesPurchaseStorageCount(); |
| | | }, |
| | | |
| | | async loadProductCategoryDistribution() { |
| | | const res = await this.$http.get('/home/productCategoryDistribution'); |
| | | this.productCategoryData = res.data.items || []; |
| | | this.renderCategoryChart(); |
| | | }, |
| | | |
| | | renderCategoryChart() { |
| | | const chart = this.$echarts.init(this.$refs.categoryChart); |
| | | const seriesData = []; |
| | | const legendData = []; |
| | | |
| | | this.productCategoryData.forEach(major => { |
| | | legendData.push(major.name); |
| | | seriesData.push({ |
| | | name: major.name, |
| | | value: parseInt(major.value) || 0, |
| | | children: (major.children || []).map(child => ({ |
| | | name: child.name, |
| | | value: parseInt(child.value) || 0, |
| | | })) |
| | | }); |
| | | }); |
| | | |
| | | chart.setOption({ |
| | | tooltip: { trigger: 'item' }, |
| | | legend: { data: legendData, orient: 'vertical', right: 10, top: 20 }, |
| | | series: [{ |
| | | type: 'sunburst', |
| | | data: seriesData, |
| | | radius: [0, '90%'], |
| | | label: { rotate: 'radial' } |
| | | }] |
| | | }); |
| | | }, |
| | | ``` |
| | | |
| | | ## 注æäºé¡¹ |
| | | |
| | | - "éå®è®¢åæ°"ç»è®¡çæ¯ sales_ledger 表ä¸ç订åè®°å½æ°ï¼æ entry_dateï¼ï¼èé sales_ledger_product 表ä¸ç产åè®°å½æ° |
| | | - æ¥æèå´çé为空æ¶ï¼é»è®¤å±ç¤ºå½åæ vs ä¸æçæ°æ® |
| | | - éè´ååå¸ç¯å½¢å¾ä¸åå°ç±»ç value ç°å¨æ¥èªå®é
çéè´æ°æ®ï¼sales_ledger_product type=2ï¼ï¼èéåæ»ç 0 |
| | | - ææç»è®¡ææ 䏿 注å½åçéæ¶æ®µï¼åç«¯ç¨ dateRange å±ç¤ºï¼ |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | # å·¡æ£ä»»å¡å®æåè½ |
| | | |
| | | ## æ¶åé¡µé¢ |
| | | |
| | | - 设å¤å·¡æ£ - å·¡æ£ä»»å¡é¡µé¢ |
| | | |
| | | ## API |
| | | |
| | | | æ¹æ³ | è·¯å¾ | 说æ | |
| | | |------|------|------| |
| | | | PUT | /inspectionTask/complete/{id} | 忡巡æ£å®æ | |
| | | | PUT | /inspectionTask/batchComplete | ä¸é®å·¡æ£å®æ | |
| | | |
| | | ### 1. å·¡æ£å®æ |
| | | |
| | | **请æ±åæ°ï¼** |
| | | |
| | | | åæ° | ç±»å | å¿
å¡« | 说æ | |
| | | |------|------|------|------| |
| | | | id | Long | æ¯ | å·¡æ£ä»»å¡IDï¼è·¯å¾åæ°ï¼ | |
| | | |
| | | **ååºï¼** |
| | | ```json |
| | | { "code": 200, "msg": "æä½æå" } |
| | | ``` |
| | | |
| | | ### 2. ä¸é®å·¡æ£å®æ |
| | | |
| | | **请æ±åæ°ï¼** |
| | | |
| | | | åæ° | ç±»å | å¿
å¡« | 说æ | |
| | | |------|------|------|------| |
| | | | dateStr | String | æ¯ | æ¥æï¼æ ¼å¼ï¼yyyy-MM-ddï¼ | |
| | | |
| | | **ååºï¼** |
| | | ```json |
| | | { "code": 200, "msg": "æä½æå" } |
| | | ``` |
| | | |
| | | ## å端修æ¹ç¹ |
| | | |
| | | ### 1. å·¡æ£ä»»å¡å表æ¹é - ææ¥æåç»æå |
| | | |
| | | åç
§éå®/éè´è®¢åå¸å±ï¼å°å·¡æ£è®°å½ææ¥æåç»æå å±ç¤ºã |
| | | |
| | | ```html |
| | | <el-collapse v-model="activeDateGroups" accordion> |
| | | <el-collapse-item v-for="group in groupedInspectionList" :key="group.dateStr" :name="group.dateStr"> |
| | | <template slot="title"> |
| | | <div class="group-header"> |
| | | <span>{{ group.dateStr }}</span> |
| | | <span>å
± {{ group.items.length }} æ¡</span> |
| | | <el-button type="success" size="small" @click.stop="handleBatchComplete(group.dateStr)">ä¸é®å·¡æ£å®æ</el-button> |
| | | </div> |
| | | </template> |
| | | <el-table :data="group.items" border> |
| | | <el-table-column prop="taskName" label="å·¡æ£ä»»å¡åç§°" /> |
| | | <el-table-column prop="inspectionProject" label="å·¡æ£é¡¹ç®" /> |
| | | <el-table-column prop="inspector" label="å·¡æ£äºº" /> |
| | | <el-table-column prop="inspectionResult" label="å·¡æ£ç»æ"> |
| | | <template slot-scope="scope"> |
| | | <el-tag v-if="scope.row.inspectionResult === '1'" type="success">æ£å¸¸</el-tag> |
| | | <el-tag v-else-if="scope.row.inspectionResult === '0'" type="danger">å¼å¸¸</el-tag> |
| | | <el-tag v-else type="info">æªå®æ</el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="status" label="ç¶æ"> |
| | | <template slot-scope="scope"> |
| | | <el-tag :type="scope.row.status === 0 ? 'warning' : 'success'"> |
| | | {{ scope.row.status === 0 ? 'å¾
å·¡æ£' : '已宿' }} |
| | | </el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="æä½" width="120"> |
| | | <template slot-scope="scope"> |
| | | <el-button v-if="scope.row.status === 0" type="primary" size="small" @click="handleComplete(scope.row.id)"> |
| | | å·¡æ£å®æ |
| | | </el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | </el-collapse-item> |
| | | </el-collapse> |
| | | ``` |
| | | |
| | | ### 2. data æ°æ® |
| | | |
| | | ```js |
| | | data() { |
| | | return { |
| | | activeDateGroups: [], |
| | | inspectionList: [], |
| | | } |
| | | } |
| | | ``` |
| | | |
| | | ### 3. 计ç®å±æ§ |
| | | |
| | | ```js |
| | | computed: { |
| | | groupedInspectionList() { |
| | | const groups = {}; |
| | | this.inspectionList.forEach(item => { |
| | | const dateStr = item.dateStr; // å端已è¿å dateStr åæ®µ |
| | | if (!groups[dateStr]) { |
| | | groups[dateStr] = { dateStr, items: [] }; |
| | | } |
| | | groups[dateStr].items.push(item); |
| | | }); |
| | | return Object.values(groups).sort((a, b) => b.dateStr.localeCompare(a.dateStr)); |
| | | } |
| | | } |
| | | ``` |
| | | |
| | | ### 4. æ¹æ³ |
| | | |
| | | ```js |
| | | async handleComplete(id) { |
| | | try { |
| | | await this.$confirm('确认该巡æ£ä»»å¡å·²å®æï¼', 'æç¤º', { type: 'warning' }); |
| | | await this.$http.put(`/inspectionTask/complete/${id}`); |
| | | this.$message.success('å·¡æ£å®æ'); |
| | | this.loadList(); |
| | | } catch (e) { |
| | | if (e !== 'cancel') { |
| | | this.$message.error(e.msg || 'æä½å¤±è´¥'); |
| | | } |
| | | } |
| | | }, |
| | | |
| | | async handleBatchComplete(dateStr) { |
| | | try { |
| | | await this.$confirm(`ç¡®è®¤å° ${dateStr} çææå¾
å·¡æ£ä»»å¡ä¸é®å®æï¼`, 'æç¤º', { type: 'warning' }); |
| | | await this.$http.put('/inspectionTask/batchComplete', null, { params: { dateStr } }); |
| | | this.$message.success('æ¹éå·¡æ£å®æ'); |
| | | this.loadList(); |
| | | } catch (e) { |
| | | if (e !== 'cancel') { |
| | | this.$message.error(e.msg || 'æä½å¤±è´¥'); |
| | | } |
| | | } |
| | | }, |
| | | |
| | | async loadList() { |
| | | const res = await this.$http.get('/inspectionTask/list', { params: this.queryParams }); |
| | | this.inspectionList = res.data.records || []; |
| | | } |
| | | ``` |
| | | |
| | | ## 注æäºé¡¹ |
| | | |
| | | - 已宿ï¼status=1ï¼çå·¡æ£è®°å½ä¸æ¾ç¤º"å·¡æ£å®æ"æé® |
| | | - ä¸é®å·¡æ£å®æä»
å¤çå½å¤©ææå¾
å·¡æ£ï¼status=0ï¼çè®°å½ |
| | | - å·¡æ£å®ææ¶è¥æªè®¾ç½®å·¡æ£ç»æï¼é»è®¤è®¾ä¸º"æ£å¸¸" |
| | | - æ°æ®åºæ°å¢äº status åæ®µï¼é¨ç½²åéæ§è¡è¿ç§» SQL |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | # ä¿å
»ä»»å¡å®æåè½ |
| | | |
| | | ## æ¶åé¡µé¢ |
| | | |
| | | - 设å¤ä¿å
» - ä¿å
»ä»»å¡é¡µé¢ |
| | | |
| | | ## API |
| | | |
| | | | æ¹æ³ | è·¯å¾ | 说æ | |
| | | |------|------|------| |
| | | | PUT | /device/maintenance/complete/{id} | åæ¡ä¿å
»å®æ | |
| | | | PUT | /device/maintenance/batchComplete | ä¸é®ä¿å
»å®æ | |
| | | |
| | | ### 1. ä¿å
»å®æ |
| | | |
| | | **请æ±åæ°ï¼** |
| | | |
| | | | åæ° | ç±»å | å¿
å¡« | 说æ | |
| | | |------|------|------|------| |
| | | | id | Long | æ¯ | ä¿å
»è®°å½IDï¼è·¯å¾åæ°ï¼ | |
| | | |
| | | **ååºï¼** `{ "code": 200, "msg": "æä½æå" }` |
| | | |
| | | ### 2. ä¸é®ä¿å
»å®æ |
| | | |
| | | **请æ±åæ°ï¼** |
| | | |
| | | | åæ° | ç±»å | å¿
å¡« | 说æ | |
| | | |------|------|------|------| |
| | | | dateStr | String | æ¯ | æ¥æï¼æ ¼å¼ï¼yyyy-MM-ddï¼ | |
| | | |
| | | **ååºï¼** `{ "code": 200, "msg": "已宿 N æ¡ä¿å
»è®°å½" }` |
| | | |
| | | ## å端修æ¹ç¹ |
| | | |
| | | ### 1. ä¿å
»ä»»å¡å表æ¹é - ææ¥æåç»æå |
| | | |
| | | åç
§éå®/éè´è®¢åæ ·å¼ï¼å°ä¿å
»è®°å½ææ¥æåç»æå å±ç¤ºã |
| | | |
| | | ```html |
| | | <el-collapse v-model="activeDateGroups" accordion> |
| | | <el-collapse-item v-for="group in groupedMaintenanceList" :key="group.dateStr" :name="group.dateStr"> |
| | | <template slot="title"> |
| | | <div class="group-header"> |
| | | <span>{{ group.dateStr }}</span> |
| | | <span>å
± {{ group.items.length }} æ¡</span> |
| | | <el-button type="success" size="small" @click.stop="handleBatchComplete(group.dateStr)">ä¸é®ä¿å
»å®æ</el-button> |
| | | </div> |
| | | </template> |
| | | <el-table :data="group.items" border> |
| | | <el-table-column prop="deviceName" label="设å¤åç§°" /> |
| | | <el-table-column prop="deviceModel" label="è§æ ¼åå·" /> |
| | | <el-table-column prop="machineryCategory" label="设å¤é¡¹ç®" /> |
| | | <el-table-column prop="maintenanceActuallyName" label="ä¿å
»äºº" /> |
| | | <el-table-column prop="status" label="ç¶æ"> |
| | | <template slot-scope="scope"> |
| | | <el-tag :type="scope.row.status === 0 ? 'warning' : 'success'"> |
| | | {{ scope.row.status === 0 ? 'å¾
ä¿å
»' : 'å·²å®ç»' }} |
| | | </el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="æä½" width="120"> |
| | | <template slot-scope="scope"> |
| | | <el-button v-if="scope.row.status === 0" type="primary" size="small" @click="handleComplete(scope.row.id)"> |
| | | ä¿å
»å®æ |
| | | </el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | </el-collapse-item> |
| | | </el-collapse> |
| | | ``` |
| | | |
| | | ### 2. data æ°æ® |
| | | |
| | | ```js |
| | | data() { |
| | | return { |
| | | activeDateGroups: [], |
| | | maintenanceList: [], |
| | | } |
| | | } |
| | | ``` |
| | | |
| | | ### 3. 计ç®å±æ§ |
| | | |
| | | ```js |
| | | computed: { |
| | | groupedMaintenanceList() { |
| | | const groups = {}; |
| | | this.maintenanceList.forEach(item => { |
| | | const dateStr = item.createTime.substring(0, 10); // 忥æé¨å yyyy-MM-dd |
| | | if (!groups[dateStr]) { |
| | | groups[dateStr] = { dateStr, items: [] }; |
| | | } |
| | | groups[dateStr].items.push(item); |
| | | }); |
| | | return Object.values(groups).sort((a, b) => b.dateStr.localeCompare(a.dateStr)); |
| | | } |
| | | } |
| | | ``` |
| | | |
| | | ### 4. æ¹æ³ |
| | | |
| | | ```js |
| | | async handleComplete(id) { |
| | | try { |
| | | await this.$confirm('确认该ä¿å
»ä»»å¡å·²å®æï¼', 'æç¤º', { type: 'warning' }); |
| | | await this.$http.put(`/device/maintenance/complete/${id}`); |
| | | this.$message.success('ä¿å
»å®æ'); |
| | | this.loadList(); |
| | | } catch (e) { |
| | | if (e !== 'cancel') { |
| | | this.$message.error(e.msg || 'æä½å¤±è´¥'); |
| | | } |
| | | } |
| | | }, |
| | | |
| | | async handleBatchComplete(dateStr) { |
| | | try { |
| | | await this.$confirm(`ç¡®è®¤å° ${dateStr} çææå¾
ä¿å
»ä»»å¡ä¸é®å®æï¼`, 'æç¤º', { type: 'warning' }); |
| | | await this.$http.put('/device/maintenance/batchComplete', null, { params: { dateStr } }); |
| | | this.$message.success('æ¹éä¿å
»å®æ'); |
| | | this.loadList(); |
| | | } catch (e) { |
| | | if (e !== 'cancel') { |
| | | this.$message.error(e.msg || 'æä½å¤±è´¥'); |
| | | } |
| | | } |
| | | }, |
| | | |
| | | async loadList() { |
| | | const res = await this.$http.get('/device/maintenance/page', { params: this.queryParams }); |
| | | this.maintenanceList = res.data.records || []; |
| | | } |
| | | ``` |
| | | |
| | | ## 注æäºé¡¹ |
| | | |
| | | - 已宿ï¼status=1ï¼çä¿å
»è®°å½ä¸æ¾ç¤º"ä¿å
»å®æ"æé® |
| | | - ä¸é®ä¿å
»å®æä»
å¤çå½å¤©ææå¾
ä¿å
»ï¼status=0ï¼çè®°å½ |
| | | - ä¿å
»å®æå status å为 1ï¼åæ¶è®°å½å½åæä½äººä¸ºå®é
ä¿å
»äºº |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | # å¤ä»¶ç¬ç«åºåº |
| | | |
| | | ## æ¶åé¡µé¢ |
| | | |
| | | - å¤ä»¶é¢ç¨è®°å½é¡µé¢ |
| | | |
| | | ## API |
| | | |
| | | | æ¹æ³ | è·¯å¾ | 说æ | |
| | | |------|------|------| |
| | | | POST | /sparePartsRequisitionRecord/outbound | å¤ä»¶ç¬ç«åºåº | |
| | | |
| | | **请æ±åæ°ï¼** |
| | | |
| | | | åæ° | ç±»å | å¿
å¡« | 说æ | |
| | | |------|------|------|------| |
| | | | sparePartsId | Long | æ¯ | å¤ä»¶ID | |
| | | | quantity | Integer | æ¯ | åºåºæ°é | |
| | | | deviceLedgerId | Long | å¦ | 设å¤ID | |
| | | | remark | String | å¦ | 夿³¨ | |
| | | |
| | | **请æ±ç¤ºä¾ï¼** |
| | | ```json |
| | | { |
| | | "sparePartsId": 1, |
| | | "quantity": 5, |
| | | "deviceLedgerId": 10, |
| | | "remark": "ç´æ¥é¢ç¨" |
| | | } |
| | | ``` |
| | | |
| | | **ååºï¼** `{ "code": 200, "msg": "æä½æå" }` |
| | | |
| | | ## å端修æ¹ç¹ |
| | | |
| | | ### 1. æ°å¢åºåºæé®/å¼¹çª |
| | | |
| | | å¨å¤ä»¶é¢ç¨è®°å½é¡µé¢æ°å¢ãå¤ä»¶åºåºãæé®ï¼ç¹å»åå¼¹åºåºåºè¡¨åã |
| | | |
| | | ```html |
| | | <el-button type="primary" @click="handleOpenOutbound">å¤ä»¶åºåº</el-button> |
| | | |
| | | <el-dialog title="å¤ä»¶åºåº" :visible.sync="outboundDialogVisible" width="500px"> |
| | | <el-form :model="outboundForm" :rules="outboundRules" ref="outboundFormRef" label-width="100px"> |
| | | <el-form-item label="éæ©å¤ä»¶" prop="sparePartsId"> |
| | | <el-select v-model="outboundForm.sparePartsId" placeholder="è¯·éæ©å¤ä»¶" filterable> |
| | | <el-option v-for="item in sparePartsList" :key="item.id" :label="item.name" :value="item.id" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="åºåºæ°é" prop="quantity"> |
| | | <el-input-number v-model="outboundForm.quantity" :min="1" /> |
| | | </el-form-item> |
| | | <el-form-item label="å
³è设å¤" prop="deviceLedgerId"> |
| | | <el-select v-model="outboundForm.deviceLedgerId" placeholder="è¯·éæ©è®¾å¤ï¼å¯éï¼" filterable clearable> |
| | | <el-option v-for="item in deviceList" :key="item.id" :label="item.deviceName" :value="item.id" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="夿³¨" prop="remark"> |
| | | <el-input v-model="outboundForm.remark" type="textarea" /> |
| | | </el-form-item> |
| | | </el-form> |
| | | <span slot="footer"> |
| | | <el-button @click="outboundDialogVisible = false">åæ¶</el-button> |
| | | <el-button type="primary" @click="handleOutboundSubmit">确认åºåº</el-button> |
| | | </span> |
| | | </el-dialog> |
| | | ``` |
| | | |
| | | ### 2. data æ°æ® |
| | | |
| | | ```js |
| | | data() { |
| | | return { |
| | | outboundDialogVisible: false, |
| | | outboundForm: { |
| | | sparePartsId: null, |
| | | quantity: 1, |
| | | deviceLedgerId: null, |
| | | remark: '', |
| | | }, |
| | | outboundRules: { |
| | | sparePartsId: [{ required: true, message: 'è¯·éæ©å¤ä»¶', trigger: 'change' }], |
| | | quantity: [{ required: true, message: '请è¾å
¥åºåºæ°é', trigger: 'blur' }], |
| | | }, |
| | | sparePartsList: [], |
| | | deviceList: [], |
| | | } |
| | | } |
| | | ``` |
| | | |
| | | ### 3. æ¹æ³ |
| | | |
| | | ```js |
| | | handleOpenOutbound() { |
| | | this.outboundForm = { sparePartsId: null, quantity: 1, deviceLedgerId: null, remark: '' }; |
| | | this.outboundDialogVisible = true; |
| | | this.loadSparePartsList(); |
| | | this.loadDeviceList(); |
| | | }, |
| | | |
| | | handleOutboundSubmit() { |
| | | this.$refs.outboundFormRef.validate(async (valid) => { |
| | | if (!valid) return; |
| | | try { |
| | | await this.$http.post('/sparePartsRequisitionRecord/outbound', this.outboundForm); |
| | | this.$message.success('åºåºæå'); |
| | | this.outboundDialogVisible = false; |
| | | this.loadList(); // å·æ°é¢ç¨è®°å½å表 |
| | | } catch (e) { |
| | | this.$message.error(e.msg || 'åºåºå¤±è´¥'); |
| | | } |
| | | }); |
| | | }, |
| | | |
| | | async loadSparePartsList() { |
| | | const res = await this.$http.get('/spareParts/listPage'); |
| | | this.sparePartsList = res.data.records || []; |
| | | }, |
| | | |
| | | async loadDeviceList() { |
| | | const res = await this.$http.get('/device/ledger/page'); |
| | | this.deviceList = res.data.records || []; |
| | | }, |
| | | ``` |
| | | |
| | | ## 注æäºé¡¹ |
| | | |
| | | - åºåºä¼æ£åå¤ä»¶åºåï¼è¯·ç¡®è®¤æ°éåç¡® |
| | | - é¢ç¨è®°å½æ¥æºç±»å伿 记为"ç´æ¥åºåº" |
| | | - å¤ä»¶åºåä¸è¶³æ¶æ¥å£ä¼è¿åé误æç¤º |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | # å¢å¼ç¨å¯¹æ¯é¡µé¢ä¼å |
| | | |
| | | ## æ¶åé¡µé¢ |
| | | |
| | | - å³çåæ - å¢å¼ç¨å¯¹æ¯é¡µé¢ |
| | | |
| | | ## API |
| | | |
| | | | æ¹æ³ | è·¯å¾ | 说æ | |
| | | |------|------|------| |
| | | | GET | /purchase/report/listVat | å¢å¼ç¨æææ±æ»ï¼åæï¼ | |
| | | | GET | /purchase/report/listVatDetail | å¢å¼ç¨æç»-æå票/订åå±ç¤ºï¼æ°å¢ï¼ | |
| | | |
| | | ### å¢å¼ç¨æç»æ¥å£ |
| | | |
| | | **请æ±åæ°ï¼** |
| | | |
| | | | åæ° | ç±»å | å¿
å¡« | 说æ | |
| | | |------|------|------|------| |
| | | | page | Page | å¦ | å页忰 | |
| | | | month | String | å¦ | æä»½çéï¼yyyy-MMï¼ï¼ä¸ºç©ºåæ¥è¯¢å
¨é¨ | |
| | | |
| | | **ååºæ ¼å¼ï¼** |
| | | ```json |
| | | { |
| | | "code": 200, |
| | | "msg": "æä½æå", |
| | | "data": { |
| | | "records": [ |
| | | { |
| | | "invoiceNo": "FP20260801001", |
| | | "salesContractNo": "HT20260801", |
| | | "supplierName": "ä¾åºåA", |
| | | "customerName": null, |
| | | "orderType": "è¿é¡¹", |
| | | "invoiceDate": "2026-08-01", |
| | | "taxRate": 13.00, |
| | | "jTaxAmount": 1300.00, |
| | | "xTaxAmount": 0.00, |
| | | "taxAmount": 1300.00 |
| | | }, |
| | | { |
| | | "invoiceNo": "XS20260801001", |
| | | "salesContractNo": "XS-HT20260801", |
| | | "supplierName": null, |
| | | "customerName": "客æ·B", |
| | | "orderType": "é项", |
| | | "invoiceDate": "2026-08-03", |
| | | "taxRate": 13.00, |
| | | "jTaxAmount": 0.00, |
| | | "xTaxAmount": 2600.00, |
| | | "taxAmount": 2600.00 |
| | | } |
| | | ], |
| | | "total": 100 |
| | | } |
| | | } |
| | | ``` |
| | | |
| | | ## å端修æ¹ç¹ |
| | | |
| | | ### 1. 页é¢å¸å±æ¹é - 左侧å表 + å³ä¾§æ±ç¶å¾ |
| | | |
| | | ```html |
| | | <el-row :gutter="20"> |
| | | <!-- 左侧ï¼å¢å¼ç¨æç»å表 --> |
| | | <el-col :span="14"> |
| | | <el-card> |
| | | <div slot="header"> |
| | | <span>å¢å¼ç¨æç»</span> |
| | | <el-select v-model="queryMonth" placeholder="éæ©æä»½" clearable style="float: right; width: 150px;"> |
| | | <el-option v-for="m in monthOptions" :key="m" :label="m" :value="m" /> |
| | | </el-select> |
| | | </div> |
| | | <el-table :data="vatDetailList" border v-loading="loading"> |
| | | <el-table-column prop="orderType" label="ç±»å" width="60"> |
| | | <template slot-scope="scope"> |
| | | <el-tag :type="scope.row.orderType === 'è¿é¡¹' ? 'info' : 'warning'" size="small"> |
| | | {{ scope.row.orderType }} |
| | | </el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="invoiceNo" label="å票å·" width="140" /> |
| | | <el-table-column prop="salesContractNo" label="ååå·" width="140" /> |
| | | <el-table-column prop="supplierName" label="ä¾åºå" /> |
| | | <el-table-column prop="customerName" label="客æ·" /> |
| | | <el-table-column prop="invoiceDate" label="å¼ç¥¨æ¥æ" width="110" /> |
| | | <el-table-column prop="taxRate" label="ç¨ç(%)" width="80" /> |
| | | <el-table-column prop="taxAmount" label="ç¨é¢" width="120"> |
| | | <template slot-scope="scope"> |
| | | <span :style="{ color: scope.row.orderType === 'è¿é¡¹' ? '#409EFF' : '#E6A23C' }"> |
| | | {{ scope.row.taxAmount }} |
| | | </span> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | <el-pagination |
| | | @size-change="handleSizeChange" |
| | | @current-change="handleCurrentChange" |
| | | :current-page="page.current" |
| | | :page-sizes="[10, 20, 50]" |
| | | :page-size="page.size" |
| | | :total="page.total" |
| | | layout="total, sizes, prev, pager, next" /> |
| | | </el-card> |
| | | </el-col> |
| | | |
| | | <!-- å³ä¾§ï¼æ±ç¶å¯¹æ¯å¾ --> |
| | | <el-col :span="10"> |
| | | <el-card> |
| | | <div slot="header"><span>è¿é项å¢å¼ç¨å¯¹æ¯</span></div> |
| | | <div ref="vatChart" style="height: 400px;"></div> |
| | | </el-card> |
| | | </el-col> |
| | | </el-row> |
| | | ``` |
| | | |
| | | ### 2. data æ°æ® |
| | | |
| | | ```js |
| | | data() { |
| | | return { |
| | | queryMonth: '', |
| | | monthOptions: [], |
| | | vatDetailList: [], |
| | | loading: false, |
| | | page: { current: 1, size: 20, total: 0 }, |
| | | } |
| | | } |
| | | ``` |
| | | |
| | | ### 3. æ¹æ³ |
| | | |
| | | ```js |
| | | async loadVatDetail() { |
| | | this.loading = true; |
| | | try { |
| | | const res = await this.$http.get('/purchase/report/listVatDetail', { |
| | | params: { |
| | | current: this.page.current, |
| | | size: this.page.size, |
| | | month: this.queryMonth || null, |
| | | } |
| | | }); |
| | | this.vatDetailList = res.data.records || []; |
| | | this.page.total = res.data.total || 0; |
| | | this.renderChart(); |
| | | } finally { |
| | | this.loading = false; |
| | | } |
| | | }, |
| | | |
| | | renderChart() { |
| | | const chart = this.$echarts.init(this.$refs.vatChart); |
| | | // æè®¢åç±»ååç»ç»è®¡ |
| | | const inputItems = this.vatDetailList.filter(i => i.orderType === 'è¿é¡¹'); |
| | | const outputItems = this.vatDetailList.filter(i => i.orderType === 'é项'); |
| | | chart.setOption({ |
| | | tooltip: { trigger: 'axis' }, |
| | | legend: { data: ['è¿é¡¹ç¨é¢', 'é项ç¨é¢'] }, |
| | | xAxis: { type: 'category', data: this.vatDetailList.map(i => i.invoiceNo) }, |
| | | yAxis: { type: 'value', name: 'ç¨é¢(å
)' }, |
| | | series: [ |
| | | { |
| | | name: 'è¿é¡¹ç¨é¢', |
| | | type: 'bar', |
| | | data: this.vatDetailList.map(i => i.orderType === 'è¿é¡¹' ? i.taxAmount : 0), |
| | | itemStyle: { color: '#409EFF' } |
| | | }, |
| | | { |
| | | name: 'é项ç¨é¢', |
| | | type: 'bar', |
| | | data: this.vatDetailList.map(i => i.orderType === 'é项' ? i.taxAmount : 0), |
| | | itemStyle: { color: '#E6A23C' } |
| | | } |
| | | ] |
| | | }); |
| | | }, |
| | | |
| | | handleSizeChange(val) { this.page.size = val; this.loadVatDetail(); }, |
| | | handleCurrentChange(val) { this.page.current = val; this.loadVatDetail(); }, |
| | | ``` |
| | | |
| | | ## 注æäºé¡¹ |
| | | |
| | | - å表å±ç¤ºæ¯æ¡å票/订å级å«çç¨é¢æç»ï¼èé以ååªæææ±æ»ï¼ |
| | | - è¿é¡¹ç¨æ¥èªéè´å票ï¼invoice_ledgerï¼ï¼éé¡¹ç¨æ¥èªéå®å¼ç¥¨ï¼ticket_registrationï¼ |
| | | - å³ä¾§æ±ç¶å¾ä½¿ç¨ ECharts å®ç°ï¼æå票å·åç»å±ç¤ºè¿éå¯¹æ¯ |
| | | - month çéåæ°ä¸ºç©ºæ¶æ¥è¯¢å
¨é¨æ°æ® |
| | |
| | | @Getter |
| | | public enum SparePartsRequisitionRecordSourceTypeEnum implements BaseEnum<Integer> { |
| | | SparePartsRequisitionRecordSourceTypeRepair(0, "ç»´ä¿®"), |
| | | SparePartsRequisitionRecordSourceTypeMaintenance(1, "ä¿å
»"); |
| | | SparePartsRequisitionRecordSourceTypeMaintenance(1, "ä¿å
»"), |
| | | SparePartsRequisitionRecordSourceTypeDirectOutbound(2, "ç´æ¥åºåº"); |
| | | |
| | | private final Integer code; |
| | | private final String value; |
| | |
| | | deviceMaintenanceService.export(response, ids); |
| | | } |
| | | |
| | | @PutMapping("/complete/{id}") |
| | | @Operation(summary = "ä¿å
»å®æ") |
| | | public AjaxResult complete(@PathVariable Long id) { |
| | | return deviceMaintenanceService.complete(id); |
| | | } |
| | | |
| | | @PutMapping("/batchComplete") |
| | | @Operation(summary = "ä¸é®ä¿å
»å®æ") |
| | | public AjaxResult batchComplete(String dateStr) { |
| | | return deviceMaintenanceService.batchComplete(dateStr); |
| | | } |
| | | |
| | | } |
| | |
| | | @Schema(description = "ä¿å
»å¾ç") |
| | | private List<StorageBlobDTO> storageBlobDTOs; |
| | | |
| | | @Schema(description = "æ¥æåç»å段(yyyy-MM-dd)") |
| | | private String dateStr; |
| | | |
| | | } |
| | | |
| | |
| | | void export(HttpServletResponse response, Long[] ids); |
| | | |
| | | DeviceMaintenanceVo detailById(Long id); |
| | | |
| | | AjaxResult complete(Long id); |
| | | |
| | | AjaxResult batchComplete(String dateStr); |
| | | } |
| | |
| | | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
| | | import com.ruoyi.basic.enums.RecordTypeEnum; |
| | | import com.ruoyi.basic.utils.FileUtil; |
| | | import com.ruoyi.common.utils.SecurityUtils; |
| | | import com.ruoyi.common.utils.bean.BeanUtils; |
| | | import com.ruoyi.common.utils.poi.ExcelUtil; |
| | | import com.ruoyi.device.dto.DeviceMaintenanceDto; |
| | |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | |
| | | import java.math.BigDecimal; |
| | | import java.time.LocalDate; |
| | | import java.time.LocalDateTime; |
| | | import java.time.LocalTime; |
| | | import java.util.ArrayList; |
| | | import java.util.List; |
| | | |
| | |
| | | vo.setStorageBlobVOs(fileUtil.getStorageBlobVOsByRecordTypeAndRecordId(RecordTypeEnum.DEVICE_MAINTENANCE, id)); |
| | | return vo; |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public AjaxResult complete(Long id) { |
| | | DeviceMaintenance record = this.getById(id); |
| | | if (record == null) { |
| | | return AjaxResult.error("ä¿å
»è®°å½ä¸åå¨"); |
| | | } |
| | | if (record.getStatus() != null && record.getStatus() == 1) { |
| | | return AjaxResult.error("该ä¿å
»è®°å½å·²å®æ"); |
| | | } |
| | | record.setStatus(1); |
| | | record.setMaintenanceActuallyName(SecurityUtils.getLoginUser().getNickName()); |
| | | record.setMaintenanceActuallyTime(LocalDateTime.now()); |
| | | this.updateById(record); |
| | | return AjaxResult.success(); |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public AjaxResult batchComplete(String dateStr) { |
| | | if (StringUtils.isBlank(dateStr)) { |
| | | return AjaxResult.error("æ¥æåæ°ä¸è½ä¸ºç©º"); |
| | | } |
| | | LocalDate date = LocalDate.parse(dateStr); |
| | | LocalDateTime startOfDay = date.atStartOfDay(); |
| | | LocalDateTime endOfDay = date.atTime(LocalTime.MAX); |
| | | List<DeviceMaintenance> records = this.lambdaQuery() |
| | | .eq(DeviceMaintenance::getStatus, 0) |
| | | .ge(DeviceMaintenance::getCreateTime, startOfDay) |
| | | .le(DeviceMaintenance::getCreateTime, endOfDay) |
| | | .list(); |
| | | if (records.isEmpty()) { |
| | | return AjaxResult.error("è¯¥æ¥æä¸æ²¡æå¾
宿çä¿å
»è®°å½"); |
| | | } |
| | | String nickName = SecurityUtils.getLoginUser().getNickName(); |
| | | LocalDateTime now = LocalDateTime.now(); |
| | | for (DeviceMaintenance record : records) { |
| | | record.setStatus(1); |
| | | record.setMaintenanceActuallyName(nickName); |
| | | record.setMaintenanceActuallyTime(now); |
| | | } |
| | | this.updateBatchById(records); |
| | | return AjaxResult.success("已宿 " + records.size() + " æ¡ä¿å
»è®°å½"); |
| | | } |
| | | } |
| | |
| | | /********************************************************è¥ééè´ç±»**************************************************/ |
| | | @GetMapping("/supplierPurchaseRanking") |
| | | @Operation(summary = "ä¾åºåéè´æå") |
| | | public AjaxResult supplierPurchaseRanking(@DefaultType Integer type) { |
| | | List<SupplierPurchaseRankingDto> list = homeService.supplierPurchaseRanking(type); |
| | | public AjaxResult supplierPurchaseRanking(@DefaultType Integer type, |
| | | @RequestParam(required = false) String startDate, |
| | | @RequestParam(required = false) String endDate) { |
| | | List<SupplierPurchaseRankingDto> list = homeService.supplierPurchaseRanking(type, startDate, endDate); |
| | | return AjaxResult.success(list); |
| | | } |
| | | |
| | |
| | | |
| | | @GetMapping("/customerContributionRanking") |
| | | @Operation(summary = "客æ·éé¢è´¡ç®æå") |
| | | public AjaxResult customerContributionRanking(@DefaultType Integer type) { |
| | | List<CustomerContributionRankingDto> list = homeService.customerContributionRanking(type); |
| | | public AjaxResult customerContributionRanking(@DefaultType Integer type, |
| | | @RequestParam(required = false) String startDate, |
| | | @RequestParam(required = false) String endDate) { |
| | | List<CustomerContributionRankingDto> list = homeService.customerContributionRanking(type, startDate, endDate); |
| | | return AjaxResult.success(list); |
| | | } |
| | | |
| | | @GetMapping("/productSalesAnalysis") |
| | | @Operation(summary = "å产åéå®éé¢åæ") |
| | | public AjaxResult productSalesAnalysis() { |
| | | List<MapDto> list = homeService.productSalesAnalysis(); |
| | | public AjaxResult productSalesAnalysis( |
| | | @RequestParam(required = false) String startDate, |
| | | @RequestParam(required = false) String endDate) { |
| | | List<MapDto> list = homeService.productSalesAnalysis(startDate, endDate); |
| | | return AjaxResult.success(list); |
| | | } |
| | | |
| | | @GetMapping("/rawMaterialPurchaseAmountRatio") |
| | | @Operation(summary = "åææéè´éé¢å æ¯") |
| | | public AjaxResult rawMaterialPurchaseAmountRatio(){ |
| | | List<MapDto> list = homeService.rawMaterialPurchaseAmountRatio(); |
| | | public AjaxResult rawMaterialPurchaseAmountRatio( |
| | | @RequestParam(required = false) String startDate, |
| | | @RequestParam(required = false) String endDate){ |
| | | List<MapDto> list = homeService.rawMaterialPurchaseAmountRatio(startDate, endDate); |
| | | return AjaxResult.success(list); |
| | | } |
| | | |
| | |
| | | |
| | | @GetMapping("/salesPurchaseStorageProductCount") |
| | | @Operation(summary = "éå®-éè´-å¨åäº§åæ°") |
| | | public AjaxResult salesPurchaseStorageProductCount(){ |
| | | List<MapDto> list = homeService.salesPurchaseStorageProductCount(); |
| | | public AjaxResult salesPurchaseStorageProductCount( |
| | | @RequestParam(required = false) String startDate, |
| | | @RequestParam(required = false) String endDate){ |
| | | List<MapDto> list = homeService.salesPurchaseStorageProductCount(startDate, endDate); |
| | | return AjaxResult.success(list); |
| | | } |
| | | |
| | | @GetMapping("/productInOutAnalysis") |
| | | @Operation(summary = "产ååºå
¥åºåæ") |
| | | public AjaxResult productInOutAnalysis(@DefaultType Integer type){ |
| | | List<Map<String, Object>> result = homeService.productInOutAnalysis(type); |
| | | public AjaxResult productInOutAnalysis(@DefaultType Integer type, |
| | | @RequestParam(required = false) String startDate, |
| | | @RequestParam(required = false) String endDate){ |
| | | List<Map<String, Object>> result = homeService.productInOutAnalysis(type, startDate, endDate); |
| | | return AjaxResult.success(result); |
| | | } |
| | | |
| | | @GetMapping("/productTurnoverDays") |
| | | @Operation(summary = "产åå¨è½¬å¤©æ°") |
| | | public AjaxResult productTurnoverDays(){ |
| | | List<MapDto> list = homeService.productTurnoverDays(); |
| | | public AjaxResult productTurnoverDays( |
| | | @RequestParam(required = false) String startDate, |
| | | @RequestParam(required = false) String endDate){ |
| | | List<MapDto> list = homeService.productTurnoverDays(startDate, endDate); |
| | | return AjaxResult.success(list); |
| | | } |
| | | |
| | |
| | | |
| | | import com.ruoyi.dto.MapDto; |
| | | import org.apache.ibatis.annotations.Mapper; |
| | | import org.apache.ibatis.annotations.Param; |
| | | import java.util.List; |
| | | |
| | | /** |
| | |
| | | public interface HomeMapper { |
| | | /** |
| | | * æ¥è¯¢äº§åå¨è½¬å¤©æ° |
| | | * |
| | | * |
| | | * @return 产åå¨è½¬å¤©æ°å表 |
| | | */ |
| | | List<MapDto> productTurnoverDays(); |
| | | |
| | | List<MapDto> productTurnoverDaysByDate(@Param("startDate") String startDate, @Param("endDate") String endDate); |
| | | |
| | | /** |
| | | * æ¥è¯¢éè´å大类åå¸ï¼å产åå°ç±»çéè´æ°é/éé¢ï¼ |
| | | * |
| | | * @return éè´åå¸å表 |
| | | */ |
| | | List<MapDto> selectPurchaseCategoryDistribution(); |
| | | } |
| | |
| | | |
| | | HomeSummaryDto summaryStatistics(); |
| | | |
| | | List<SupplierPurchaseRankingDto> supplierPurchaseRanking(Integer type); |
| | | List<SupplierPurchaseRankingDto> supplierPurchaseRanking(Integer type, String startDate, String endDate); |
| | | |
| | | CustomerRevenueAnalysisDto customerRevenueAnalysis(Long customerId, Integer type); |
| | | |
| | | ProductCategoryDistributionDto productCategoryDistribution(); |
| | | |
| | | List<CustomerContributionRankingDto> customerContributionRanking(Integer type); |
| | | List<CustomerContributionRankingDto> customerContributionRanking(Integer type, String startDate, String endDate); |
| | | |
| | | List<MapDto> productSalesAnalysis(); |
| | | List<MapDto> productSalesAnalysis(String startDate, String endDate); |
| | | |
| | | List<MapDto> rawMaterialPurchaseAmountRatio(); |
| | | List<MapDto> rawMaterialPurchaseAmountRatio(String startDate, String endDate); |
| | | |
| | | List<MapDto> salesPurchaseStorageProductCount(); |
| | | List<MapDto> salesPurchaseStorageProductCount(String startDate, String endDate); |
| | | |
| | | List<Map<String, Object>> productInOutAnalysis(Integer type); |
| | | List<Map<String, Object>> productInOutAnalysis(Integer type, String startDate, String endDate); |
| | | |
| | | List<MapDto> productTurnoverDays(); |
| | | List<MapDto> productTurnoverDays(String startDate, String endDate); |
| | | |
| | | List<Map<String, Object>> incomeExpenseAnalysis(Integer type); |
| | | |
| | |
| | | } |
| | | |
| | | @Override |
| | | public List<SupplierPurchaseRankingDto> supplierPurchaseRanking(Integer type) { |
| | | LocalDate today = LocalDate.now(); |
| | | public List<SupplierPurchaseRankingDto> supplierPurchaseRanking(Integer type, String startDateStr, String endDateStr) { |
| | | LocalDate startDate; |
| | | LocalDate endDate; |
| | | switch (type) { |
| | | case 1: // å¨ |
| | | startDate = today.with(DayOfWeek.MONDAY); |
| | | endDate = today.with(DayOfWeek.SUNDAY); |
| | | break; |
| | | case 2: // æ |
| | | startDate = today.with(TemporalAdjusters.firstDayOfMonth()); |
| | | endDate = today.with(TemporalAdjusters.lastDayOfMonth()); |
| | | break; |
| | | case 3: // å£åº¦ |
| | | Month currentMonth = today.getMonth(); |
| | | Month firstMonthOfQuarter = currentMonth.firstMonthOfQuarter(); |
| | | Month lastMonthOfQuarter = Month.of(firstMonthOfQuarter.getValue() + 2); |
| | | |
| | | startDate = today.withMonth(firstMonthOfQuarter.getValue()).with(TemporalAdjusters.firstDayOfMonth()); |
| | | endDate = today.withMonth(lastMonthOfQuarter.getValue()).with(TemporalAdjusters.lastDayOfMonth()); |
| | | break; |
| | | default: |
| | | return new ArrayList<>(); |
| | | if (com.ruoyi.common.utils.StringUtils.isNotBlank(startDateStr) && com.ruoyi.common.utils.StringUtils.isNotBlank(endDateStr)) { |
| | | startDate = LocalDate.parse(startDateStr); |
| | | endDate = LocalDate.parse(endDateStr); |
| | | } else { |
| | | LocalDate today = LocalDate.now(); |
| | | switch (type) { |
| | | case 1: // å¨ |
| | | startDate = today.with(DayOfWeek.MONDAY); |
| | | endDate = today.with(DayOfWeek.SUNDAY); |
| | | break; |
| | | case 2: // æ |
| | | startDate = today.with(TemporalAdjusters.firstDayOfMonth()); |
| | | endDate = today.with(TemporalAdjusters.lastDayOfMonth()); |
| | | break; |
| | | case 3: // å£åº¦ |
| | | Month currentMonth = today.getMonth(); |
| | | Month firstMonthOfQuarter = currentMonth.firstMonthOfQuarter(); |
| | | Month lastMonthOfQuarter = Month.of(firstMonthOfQuarter.getValue() + 2); |
| | | startDate = today.withMonth(firstMonthOfQuarter.getValue()).with(TemporalAdjusters.firstDayOfMonth()); |
| | | endDate = today.withMonth(lastMonthOfQuarter.getValue()).with(TemporalAdjusters.lastDayOfMonth()); |
| | | break; |
| | | default: |
| | | return new ArrayList<>(); |
| | | } |
| | | } |
| | | |
| | | QueryWrapper<PurchaseLedger> queryWrapper = new QueryWrapper<>(); |
| | | queryWrapper.select("supplier_name", "SUM(contract_amount) as total_amount") |
| | | .ge("entry_date", startDate) |
| | | .le("entry_date", endDate) |
| | | // .ne("approval_status", 3) |
| | | .groupBy("supplier_name") |
| | | .orderByDesc("total_amount") |
| | | .last("LIMIT 5"); |
| | |
| | | majorDto.setRate("0.00"); |
| | | } |
| | | |
| | | // æ¥è¯¢å产åå°ç±»çéè´æ°é |
| | | Map<String, BigDecimal> purchaseDataMap = new java.util.HashMap<>(); |
| | | List<com.ruoyi.dto.MapDto> purchaseDistribution = homeMapper.selectPurchaseCategoryDistribution(); |
| | | if (purchaseDistribution != null) { |
| | | for (com.ruoyi.dto.MapDto item : purchaseDistribution) { |
| | | if (item.getName() != null && item.getValue() != null) { |
| | | purchaseDataMap.put(item.getName(), new BigDecimal(item.getValue())); |
| | | } |
| | | } |
| | | } |
| | | |
| | | BigDecimal majorTotalChildrenValue = BigDecimal.ZERO; |
| | | List<ProductCategoryDistributionDto.MinorCategoryDto> minorDtos = new ArrayList<>(); |
| | | for (Product minor : children) { |
| | | ProductCategoryDistributionDto.MinorCategoryDto minorDto = new ProductCategoryDistributionDto.MinorCategoryDto(); |
| | | minorDto.setName(minor.getProductName()); |
| | | minorDto.setValue("0"); |
| | | BigDecimal minorValue = purchaseDataMap.getOrDefault(minor.getProductName(), BigDecimal.ZERO); |
| | | minorDto.setValue(minorValue.toString()); |
| | | minorDto.setRate("0.00"); |
| | | minorDto.setChildren(new ArrayList<>()); |
| | | minorDtos.add(minorDto); |
| | | majorTotalChildrenValue = majorTotalChildrenValue.add(minorValue); |
| | | } |
| | | majorDto.setChildren(minorDtos); |
| | | // 使ç¨å®é
éè´æ°æ®æ´æ°å¤§ç±»ç value |
| | | if (majorTotalChildrenValue.compareTo(BigDecimal.ZERO) > 0) { |
| | | majorDto.setValue(majorTotalChildrenValue.toString()); |
| | | } |
| | | majorItems.add(majorDto); |
| | | |
| | | // 计ç®å¤§ç±»å æ¯ |
| | | BigDecimal totalAllValue = BigDecimal.ZERO; |
| | | for (ProductCategoryDistributionDto.MajorCategoryDto m : majorItems) { |
| | | try { |
| | | totalAllValue = totalAllValue.add(new BigDecimal(m.getValue())); |
| | | } catch (NumberFormatException ignored) { |
| | | } |
| | | } |
| | | if (totalAllValue.compareTo(BigDecimal.ZERO) > 0) { |
| | | for (ProductCategoryDistributionDto.MajorCategoryDto m : majorItems) { |
| | | try { |
| | | BigDecimal val = new BigDecimal(m.getValue()); |
| | | m.setRate(val.divide(totalAllValue, 4, RoundingMode.HALF_UP) |
| | | .multiply(new BigDecimal("100")) |
| | | .setScale(2, RoundingMode.HALF_UP) |
| | | .toString()); |
| | | } catch (NumberFormatException ignored) { |
| | | } |
| | | } |
| | | } |
| | | // 计ç®å°ç±»å æ¯ï¼å¨å大类å
ï¼ |
| | | for (ProductCategoryDistributionDto.MajorCategoryDto m : majorItems) { |
| | | if (m.getChildren() == null || m.getChildren().isEmpty()) { |
| | | continue; |
| | | } |
| | | BigDecimal parentVal = BigDecimal.ZERO; |
| | | for (ProductCategoryDistributionDto.MinorCategoryDto child : m.getChildren()) { |
| | | try { |
| | | parentVal = parentVal.add(new BigDecimal(child.getValue())); |
| | | } catch (NumberFormatException ignored) { |
| | | } |
| | | } |
| | | if (parentVal.compareTo(BigDecimal.ZERO) > 0) { |
| | | for (ProductCategoryDistributionDto.MinorCategoryDto child : m.getChildren()) { |
| | | try { |
| | | BigDecimal childVal = new BigDecimal(child.getValue()); |
| | | child.setRate(childVal.divide(parentVal, 4, RoundingMode.HALF_UP) |
| | | .multiply(new BigDecimal("100")) |
| | | .setScale(2, RoundingMode.HALF_UP) |
| | | .toString()); |
| | | } catch (NumberFormatException ignored) { |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | dto.setItems(majorItems); |
| | |
| | | } |
| | | |
| | | @Override |
| | | public List<CustomerContributionRankingDto> customerContributionRanking(Integer type) { |
| | | LocalDate today = LocalDate.now(); |
| | | LocalDate startDate = null; |
| | | LocalDate endDate = null; |
| | | switch (type) { |
| | | case 1: |
| | | startDate = today.with(DayOfWeek.MONDAY); |
| | | endDate = today.with(DayOfWeek.SUNDAY); |
| | | break; |
| | | case 2: |
| | | startDate = today.with(TemporalAdjusters.firstDayOfMonth()); |
| | | endDate = today.with(TemporalAdjusters.lastDayOfMonth()); |
| | | break; |
| | | case 3: |
| | | Month currentMonth = today.getMonth(); |
| | | Month firstMonthOfQuarter = currentMonth.firstMonthOfQuarter(); |
| | | Month lastMonthOfQuarter = Month.of(firstMonthOfQuarter.getValue() + 2); |
| | | startDate = today.withMonth(firstMonthOfQuarter.getValue()).with(TemporalAdjusters.firstDayOfMonth()); |
| | | endDate = today.withMonth(lastMonthOfQuarter.getValue()).with(TemporalAdjusters.lastDayOfMonth()); |
| | | break; |
| | | public List<CustomerContributionRankingDto> customerContributionRanking(Integer type, String startDateStr, String endDateStr) { |
| | | LocalDate startDate; |
| | | LocalDate endDate; |
| | | if (com.ruoyi.common.utils.StringUtils.isNotBlank(startDateStr) && com.ruoyi.common.utils.StringUtils.isNotBlank(endDateStr)) { |
| | | startDate = LocalDate.parse(startDateStr); |
| | | endDate = LocalDate.parse(endDateStr); |
| | | } else { |
| | | LocalDate today = LocalDate.now(); |
| | | switch (type) { |
| | | case 1: |
| | | startDate = today.with(DayOfWeek.MONDAY); |
| | | endDate = today.with(DayOfWeek.SUNDAY); |
| | | break; |
| | | case 2: |
| | | startDate = today.with(TemporalAdjusters.firstDayOfMonth()); |
| | | endDate = today.with(TemporalAdjusters.lastDayOfMonth()); |
| | | break; |
| | | case 3: |
| | | Month currentMonth = today.getMonth(); |
| | | Month firstMonthOfQuarter = currentMonth.firstMonthOfQuarter(); |
| | | Month lastMonthOfQuarter = Month.of(firstMonthOfQuarter.getValue() + 2); |
| | | startDate = today.withMonth(firstMonthOfQuarter.getValue()).with(TemporalAdjusters.firstDayOfMonth()); |
| | | endDate = today.withMonth(lastMonthOfQuarter.getValue()).with(TemporalAdjusters.lastDayOfMonth()); |
| | | break; |
| | | default: |
| | | return new ArrayList<>(); |
| | | } |
| | | } |
| | | |
| | | QueryWrapper<SalesLedger> queryWrapper = new QueryWrapper<>(); |
| | | queryWrapper.select("customer_name", "SUM(contract_amount) as total_amount") |
| | | .isNotNull("customer_name") |
| | | .between("entry_date", startDate, endDate) |
| | | .groupBy("customer_name") |
| | | .orderByDesc("total_amount") |
| | | .last("LIMIT 5"); |
| | | |
| | | if (startDate != null && endDate != null) { |
| | | queryWrapper.between("entry_date", startDate, endDate); |
| | | } |
| | | |
| | | List<Map<String, Object>> maps = salesLedgerMapper.selectMaps(queryWrapper); |
| | | List<CustomerContributionRankingDto> result = new ArrayList<>(); |
| | |
| | | } |
| | | |
| | | @Override |
| | | public List<MapDto> productSalesAnalysis() { |
| | | // è·åææäº§å大类çéå®é¢ |
| | | List<Map<String, Object>> analysisResults = salesLedgerProductMapper.selectProductSalesAnalysis(); |
| | | public List<MapDto> productSalesAnalysis(String startDateStr, String endDateStr) { |
| | | List<Map<String, Object>> analysisResults; |
| | | if (com.ruoyi.common.utils.StringUtils.isNotBlank(startDateStr) && com.ruoyi.common.utils.StringUtils.isNotBlank(endDateStr)) { |
| | | analysisResults = salesLedgerProductMapper.selectProductSalesAnalysisByDate(startDateStr, endDateStr); |
| | | } else { |
| | | analysisResults = salesLedgerProductMapper.selectProductSalesAnalysis(); |
| | | } |
| | | if (CollectionUtils.isEmpty(analysisResults)) { |
| | | return new ArrayList<>(); |
| | | } |
| | |
| | | } |
| | | |
| | | @Override |
| | | public List<MapDto> rawMaterialPurchaseAmountRatio() { |
| | | // è·åææåææçéè´é¢ |
| | | List<Map<String, Object>> analysisResults = salesLedgerProductMapper.selectRawMaterialPurchaseAnalysis(); |
| | | public List<MapDto> rawMaterialPurchaseAmountRatio(String startDateStr, String endDateStr) { |
| | | List<Map<String, Object>> analysisResults; |
| | | if (com.ruoyi.common.utils.StringUtils.isNotBlank(startDateStr) && com.ruoyi.common.utils.StringUtils.isNotBlank(endDateStr)) { |
| | | analysisResults = salesLedgerProductMapper.selectRawMaterialPurchaseAnalysisByDate(startDateStr, endDateStr); |
| | | } else { |
| | | analysisResults = salesLedgerProductMapper.selectRawMaterialPurchaseAnalysis(); |
| | | } |
| | | if (CollectionUtils.isEmpty(analysisResults)) { |
| | | return new ArrayList<>(); |
| | | } |
| | |
| | | } |
| | | |
| | | @Override |
| | | public List<MapDto> salesPurchaseStorageProductCount() { |
| | | public List<MapDto> salesPurchaseStorageProductCount(String startDate, String endDate) { |
| | | LocalDateTime now = LocalDateTime.now(); |
| | | LocalDateTime currentMonthStart = now.with(TemporalAdjusters.firstDayOfMonth()).with(LocalTime.MIN); |
| | | LocalDateTime lastMonth = now.minusMonths(1); |
| | | LocalDateTime lastMonthStart = lastMonth.with(TemporalAdjusters.firstDayOfMonth()).with(LocalTime.MIN); |
| | | LocalDateTime lastMonthEnd = lastMonth.with(TemporalAdjusters.lastDayOfMonth()).with(LocalTime.MAX); |
| | | LocalDateTime currentMonthStart; |
| | | LocalDateTime currentMonthEnd; |
| | | LocalDateTime lastMonthStart; |
| | | LocalDateTime lastMonthEnd; |
| | | |
| | | // éå® |
| | | int currentSales = salesLedgerProductMapper.selectProductCountByTypeAndDate(1, currentMonthStart, now); |
| | | int lastSales = salesLedgerProductMapper.selectProductCountByTypeAndDate(1, lastMonthStart, lastMonthEnd); |
| | | // éè´ |
| | | int currentPurchase = salesLedgerProductMapper.selectProductCountByTypeAndDate(2, currentMonthStart, now); |
| | | if (StringUtils.isNotBlank(startDate) && StringUtils.isNotBlank(endDate)) { |
| | | LocalDate start = LocalDate.parse(startDate); |
| | | LocalDate end = LocalDate.parse(endDate); |
| | | currentMonthStart = start.atStartOfDay(); |
| | | currentMonthEnd = end.atTime(LocalTime.MAX); |
| | | long daysBetween = java.time.temporal.ChronoUnit.DAYS.between(start, end) + 1; |
| | | LocalDate lastStart = start.minusDays(daysBetween); |
| | | LocalDate lastEnd = start.minusDays(1); |
| | | lastMonthStart = lastStart.atStartOfDay(); |
| | | lastMonthEnd = lastEnd.atTime(LocalTime.MAX); |
| | | } else { |
| | | currentMonthStart = now.with(TemporalAdjusters.firstDayOfMonth()).with(LocalTime.MIN); |
| | | currentMonthEnd = now; |
| | | LocalDateTime lastMonth = now.minusMonths(1); |
| | | lastMonthStart = lastMonth.with(TemporalAdjusters.firstDayOfMonth()).with(LocalTime.MIN); |
| | | lastMonthEnd = lastMonth.with(TemporalAdjusters.lastDayOfMonth()).with(LocalTime.MAX); |
| | | } |
| | | |
| | | // éå®è®¢åæ°ï¼ç»è®¡sales_ledgerè¡¨ï¼ |
| | | int currentSales = Math.toIntExact(salesLedgerMapper.selectCount(new LambdaQueryWrapper<SalesLedger>() |
| | | .ge(SalesLedger::getEntryDate, currentMonthStart) |
| | | .le(SalesLedger::getEntryDate, currentMonthEnd))); |
| | | int lastSales = Math.toIntExact(salesLedgerMapper.selectCount(new LambdaQueryWrapper<SalesLedger>() |
| | | .ge(SalesLedger::getEntryDate, lastMonthStart) |
| | | .le(SalesLedger::getEntryDate, lastMonthEnd))); |
| | | // éè´äº§åæ° |
| | | int currentPurchase = salesLedgerProductMapper.selectProductCountByTypeAndDate(2, currentMonthStart, currentMonthEnd); |
| | | int lastPurchase = salesLedgerProductMapper.selectProductCountByTypeAndDate(2, lastMonthStart, lastMonthEnd); |
| | | // å¨å |
| | | int currentStorage = stockInventoryMapper.selectStorageProductCountByDate(currentMonthStart, now); |
| | | // å¨åäº§åæ° |
| | | int currentStorage = stockInventoryMapper.selectStorageProductCountByDate(currentMonthStart, currentMonthEnd); |
| | | int lastStorage = stockInventoryMapper.selectStorageProductCountByDate(lastMonthStart, lastMonthEnd); |
| | | |
| | | List<MapDto> list = new ArrayList<>(); |
| | | list.add(createMapDto("éå®äº§åæ°", currentSales, lastSales)); |
| | | list.add(createMapDto("éå®è®¢åæ°", currentSales, lastSales)); |
| | | list.add(createMapDto("éè´äº§åæ°", currentPurchase, lastPurchase)); |
| | | list.add(createMapDto("å¨åäº§åæ°", currentStorage, lastStorage)); |
| | | |
| | |
| | | } |
| | | |
| | | @Override |
| | | public List<Map<String, Object>> productInOutAnalysis(Integer type) { |
| | | public List<Map<String, Object>> productInOutAnalysis(Integer type, String startDateStr, String endDateStr) { |
| | | String targetName; |
| | | if (type == 1) { |
| | | targetName = "åææ"; |
| | |
| | | LocalDate now = LocalDate.now(); |
| | | DateTimeFormatter displayDtf = DateTimeFormatter.ofPattern("M/d"); |
| | | |
| | | String startDate = now.minusDays(6).toString(); |
| | | String endDate = now.toString(); |
| | | LocalDate start; |
| | | LocalDate end; |
| | | if (com.ruoyi.common.utils.StringUtils.isNotBlank(startDateStr) && com.ruoyi.common.utils.StringUtils.isNotBlank(endDateStr)) { |
| | | start = LocalDate.parse(startDateStr); |
| | | end = LocalDate.parse(endDateStr); |
| | | } else { |
| | | end = now; |
| | | start = now.minusDays(6); |
| | | } |
| | | String startDate = start.toString(); |
| | | String endDate = end.toString(); |
| | | |
| | | List<Map<String, Object>> inCounts = stockInventoryMapper.selectDailyStockInCounts(rootCategoryId, startDate, |
| | | endDate + " 23:59:59"); |
| | |
| | | } |
| | | |
| | | @Override |
| | | public List<MapDto> productTurnoverDays() { |
| | | public List<MapDto> productTurnoverDays(String startDateStr, String endDateStr) { |
| | | if (com.ruoyi.common.utils.StringUtils.isNotBlank(startDateStr) && com.ruoyi.common.utils.StringUtils.isNotBlank(endDateStr)) { |
| | | return homeMapper.productTurnoverDaysByDate(startDateStr, endDateStr); |
| | | } |
| | | return homeMapper.productTurnoverDays(); |
| | | } |
| | | |
| | |
| | | return R.ok(inspectionTaskService.delByIds(ids)); |
| | | } |
| | | |
| | | /** |
| | | * å·¡æ£å®æ |
| | | */ |
| | | @PutMapping("/complete/{id}") |
| | | @Operation(summary = "å·¡æ£å®æ") |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public R complete(@PathVariable Long id) { |
| | | return R.ok(inspectionTaskService.complete(id)); |
| | | } |
| | | |
| | | /** |
| | | * ä¸é®å·¡æ£å®æ |
| | | */ |
| | | @PutMapping("/batchComplete") |
| | | @Operation(summary = "ä¸é®å·¡æ£å®æ") |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public R batchComplete(String dateStr) { |
| | | return R.ok(inspectionTaskService.batchComplete(dateStr)); |
| | | } |
| | | |
| | | } |
| | |
| | | @Schema(description = "å·¡æ£å°ç¹è¯¦ç»æè¿°") |
| | | private String inspectionLocation; |
| | | |
| | | @Schema(description = "ç¶æ 0=å¾
å·¡æ£, 1=已宿") |
| | | private Integer status; |
| | | |
| | | @Schema(description = "软å 餿 å¿ï¼0=æªå é¤ï¼1=å·²å é¤") |
| | | private Integer deleted; |
| | | |
| | |
| | | int addOrEditInspectionTask(InspectionTaskDto inspectionTaskDto); |
| | | |
| | | int delByIds(Long[] ids); |
| | | |
| | | int complete(Long id); |
| | | |
| | | int batchComplete(String dateStr); |
| | | } |
| | |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public int complete(Long id) { |
| | | InspectionTask task = inspectionTaskMapper.selectById(id); |
| | | if (task == null) { |
| | | throw new IllegalArgumentException("å·¡æ£ä»»å¡ä¸åå¨"); |
| | | } |
| | | if (task.getStatus() != null && task.getStatus() == 1) { |
| | | throw new IllegalArgumentException("该巡æ£ä»»å¡å·²å®æ"); |
| | | } |
| | | task.setStatus(1); |
| | | if (task.getInspectionResult() == null) { |
| | | task.setInspectionResult("1"); |
| | | } |
| | | return inspectionTaskMapper.updateById(task); |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public int batchComplete(String dateStr) { |
| | | if (StringUtils.isBlank(dateStr)) { |
| | | throw new IllegalArgumentException("æ¥æåæ°ä¸è½ä¸ºç©º"); |
| | | } |
| | | java.time.LocalDate date = java.time.LocalDate.parse(dateStr); |
| | | java.time.LocalDateTime startOfDay = date.atStartOfDay(); |
| | | java.time.LocalDateTime endOfDay = date.atTime(java.time.LocalTime.MAX); |
| | | List<InspectionTask> tasks = inspectionTaskMapper.selectList( |
| | | new LambdaQueryWrapper<InspectionTask>() |
| | | .eq(InspectionTask::getStatus, 0) |
| | | .ge(InspectionTask::getCreateTime, startOfDay) |
| | | .le(InspectionTask::getCreateTime, endOfDay)); |
| | | if (tasks.isEmpty()) { |
| | | throw new IllegalArgumentException("è¯¥æ¥æä¸æ²¡æå¾
宿çå·¡æ£è®°å½"); |
| | | } |
| | | int count = 0; |
| | | for (InspectionTask task : tasks) { |
| | | task.setStatus(1); |
| | | if (task.getInspectionResult() == null) { |
| | | task.setInspectionResult("1"); |
| | | } |
| | | inspectionTaskMapper.updateById(task); |
| | | count++; |
| | | } |
| | | return count; |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public int delByIds(Long[] ids) { |
| | | // æ£æ¥åæ° |
| | | if (ids == null || ids.length == 0) { |
| | |
| | | import com.baomidou.mybatisplus.core.metadata.IPage; |
| | | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
| | | import com.ruoyi.framework.web.domain.AjaxResult; |
| | | import com.ruoyi.measuringinstrumentledger.dto.SparePartsOutboundDto; |
| | | import com.ruoyi.measuringinstrumentledger.dto.SparePartsRequisitionRecordDto; |
| | | import com.ruoyi.measuringinstrumentledger.service.SparePartsRequisitionRecordService; |
| | | import io.swagger.v3.oas.annotations.tags.Tag; |
| | | import io.swagger.v3.oas.annotations.Operation; |
| | | import lombok.AllArgsConstructor; |
| | | import org.springframework.web.bind.annotation.GetMapping; |
| | | import org.springframework.web.bind.annotation.PostMapping; |
| | | import org.springframework.web.bind.annotation.RequestBody; |
| | | import org.springframework.web.bind.annotation.RequestMapping; |
| | | import org.springframework.web.bind.annotation.RestController; |
| | | |
| | |
| | | IPage<SparePartsRequisitionRecordDto> listPage = sparePartsRequisitionRecordService.listPage(page, sparePartsRequisitionRecordDto); |
| | | return AjaxResult.success(listPage); |
| | | } |
| | | |
| | | @PostMapping("/outbound") |
| | | @Operation(summary = "å¤ä»¶ç¬ç«åºåº") |
| | | public AjaxResult outbound(@RequestBody SparePartsOutboundDto dto){ |
| | | sparePartsRequisitionRecordService.outbound(dto); |
| | | return AjaxResult.success(); |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package com.ruoyi.measuringinstrumentledger.dto; |
| | | |
| | | import io.swagger.v3.oas.annotations.media.Schema; |
| | | import lombok.Data; |
| | | |
| | | @Data |
| | | @Schema(name = "å¤ä»¶åºåºè¯·æ±") |
| | | public class SparePartsOutboundDto { |
| | | |
| | | @Schema(description = "å¤ä»¶ID", requiredMode = Schema.RequiredMode.REQUIRED) |
| | | private Long sparePartsId; |
| | | |
| | | @Schema(description = "åºåºæ°é", requiredMode = Schema.RequiredMode.REQUIRED) |
| | | private Integer quantity; |
| | | |
| | | @Schema(description = "设å¤IDï¼å¯éï¼") |
| | | private Long deviceLedgerId; |
| | | |
| | | @Schema(description = "夿³¨ï¼å¯éï¼") |
| | | private String remark; |
| | | } |
| | |
| | | import com.baomidou.mybatisplus.core.metadata.IPage; |
| | | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
| | | import com.baomidou.mybatisplus.extension.service.IService; |
| | | import com.ruoyi.measuringinstrumentledger.dto.SparePartsOutboundDto; |
| | | import com.ruoyi.measuringinstrumentledger.dto.SparePartsRequisitionRecordDto; |
| | | import com.ruoyi.measuringinstrumentledger.pojo.SparePartsRequisitionRecord; |
| | | |
| | |
| | | */ |
| | | public interface SparePartsRequisitionRecordService extends IService<SparePartsRequisitionRecord> { |
| | | IPage<SparePartsRequisitionRecordDto> listPage(Page page, SparePartsRequisitionRecordDto sparePartsRequisitionRecordDto); |
| | | |
| | | void outbound(SparePartsOutboundDto dto); |
| | | } |
| | |
| | | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
| | | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
| | | import com.ruoyi.common.enums.SparePartsRequisitionRecordSourceTypeEnum; |
| | | import com.ruoyi.measuringinstrumentledger.dto.SparePartsOutboundDto; |
| | | import com.ruoyi.measuringinstrumentledger.dto.SparePartsRequisitionRecordDto; |
| | | import com.ruoyi.measuringinstrumentledger.mapper.SparePartsMapper; |
| | | import com.ruoyi.measuringinstrumentledger.mapper.SparePartsRequisitionRecordMapper; |
| | | import com.ruoyi.measuringinstrumentledger.pojo.SpareParts; |
| | | import com.ruoyi.measuringinstrumentledger.pojo.SparePartsRequisitionRecord; |
| | | import com.ruoyi.measuringinstrumentledger.service.SparePartsRequisitionRecordService; |
| | | import lombok.RequiredArgsConstructor; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | |
| | | import java.math.BigDecimal; |
| | | |
| | | /** |
| | | * <p> |
| | |
| | | @RequiredArgsConstructor |
| | | public class SparePartsRequisitionRecordServiceImpl extends ServiceImpl<SparePartsRequisitionRecordMapper, SparePartsRequisitionRecord> implements SparePartsRequisitionRecordService { |
| | | private final SparePartsRequisitionRecordMapper sparePartsRequisitionRecordMapper; |
| | | private final SparePartsMapper sparePartsMapper; |
| | | |
| | | @Override |
| | | public IPage<SparePartsRequisitionRecordDto> listPage(Page page, SparePartsRequisitionRecordDto sparePartsRequisitionRecordDto) { |
| | |
| | | }); |
| | | return result; |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public void outbound(SparePartsOutboundDto dto) { |
| | | SpareParts spareParts = sparePartsMapper.selectById(dto.getSparePartsId()); |
| | | if (spareParts == null) { |
| | | throw new IllegalArgumentException("å¤ä»¶ä¸åå¨"); |
| | | } |
| | | if (spareParts.getQuantity().compareTo(new BigDecimal(dto.getQuantity())) < 0) { |
| | | throw new IllegalArgumentException("å¤ä»¶ " + spareParts.getName() + " åºåä¸è¶³"); |
| | | } |
| | | // æ£ååºå |
| | | spareParts.setQuantity(spareParts.getQuantity().subtract(new BigDecimal(dto.getQuantity()))); |
| | | sparePartsMapper.updateById(spareParts); |
| | | // å建é¢ç¨è®°å½ |
| | | SparePartsRequisitionRecord record = new SparePartsRequisitionRecord(); |
| | | record.setSourceType(SparePartsRequisitionRecordSourceTypeEnum.SparePartsRequisitionRecordSourceTypeDirectOutbound.getCode()); |
| | | record.setSparePartsId(dto.getSparePartsId()); |
| | | record.setQuantity(dto.getQuantity()); |
| | | record.setDeviceLedgerId(dto.getDeviceLedgerId()); |
| | | this.save(record); |
| | | } |
| | | } |
| | |
| | | ExcelUtil<VatDto> util = new ExcelUtil<VatDto>(VatDto.class); |
| | | util.exportExcel(response, result.getRecords() , "å¢å¼ç¨æ¯å¯¹"); |
| | | } |
| | | |
| | | @GetMapping("/listVatDetail") |
| | | @Operation(summary = "å¢å¼ç¨æç»-æå票/订åå±ç¤º") |
| | | public AjaxResult listVatDetail(Page page, String month) { |
| | | IPage<VatDto> result = invoicePurchaseService.listVatDetail(page, month); |
| | | return AjaxResult.success(result); |
| | | } |
| | | } |
| | |
| | | package com.ruoyi.purchase.dto; |
| | | |
| | | import com.fasterxml.jackson.annotation.JsonFormat; |
| | | import com.ruoyi.framework.aspectj.lang.annotation.Excel; |
| | | import lombok.Data; |
| | | |
| | | import java.math.BigDecimal; |
| | | import java.time.LocalDate; |
| | | import java.time.LocalDateTime; |
| | | |
| | | @Data |
| | | public class VatDto { |
| | | |
| | | //æä»½ |
| | | //æä»½ï¼æ±æ»è§å¾ï¼ |
| | | @Excel(name = "æä»½") |
| | | private String month ; |
| | | |
| | |
| | | @Excel(name = "é-è¿") |
| | | private BigDecimal taxAmount; |
| | | |
| | | // ========== æç»è§å¾å段 ========== |
| | | |
| | | @Excel(name = "å票å·") |
| | | private String invoiceNo; |
| | | |
| | | @Excel(name = "éå®ååå·") |
| | | private String salesContractNo; |
| | | |
| | | @Excel(name = "客æ·åç§°") |
| | | private String customerName; |
| | | |
| | | @Excel(name = "ä¾åºååç§°") |
| | | private String supplierName; |
| | | |
| | | @Excel(name = "ç±»å") |
| | | private String orderType; |
| | | |
| | | @Excel(name = "å¼ç¥¨æ¥æ") |
| | | @JsonFormat(pattern = "yyyy-MM-dd") |
| | | private LocalDate invoiceDate; |
| | | |
| | | @Excel(name = "ç¨ç") |
| | | private BigDecimal taxRate; |
| | | |
| | | } |
| | |
| | | IPage<VatDto> listVat(Page page,@Param("month") String month); |
| | | |
| | | List<VatDto> listVat1(); |
| | | |
| | | IPage<VatDto> listVatDetail(Page page, @Param("month") String month); |
| | | } |
| | |
| | | IPage<InvoicePurchaseReportDto> listPurchaseReport(Page page, InvoicePurchaseReportDto invoicePurchaseReportDto); |
| | | |
| | | IPage<VatDto> listVat(Page page,String month); |
| | | |
| | | IPage<VatDto> listVatDetail(Page page, String month); |
| | | } |
| | |
| | | }); |
| | | return vatDtos; |
| | | } |
| | | |
| | | @Override |
| | | public IPage<VatDto> listVatDetail(Page page, String month) { |
| | | return invoicePurchaseMapper.listVatDetail(page, month); |
| | | } |
| | | } |
| | |
| | | |
| | | List<Map<String, Object>> selectProductSalesAnalysis(); |
| | | |
| | | List<Map<String, Object>> selectProductSalesAnalysisByDate(@Param("startDate") String startDate, @Param("endDate") String endDate); |
| | | |
| | | List<Map<String, Object>> selectRawMaterialPurchaseAnalysis(); |
| | | |
| | | List<Map<String, Object>> selectRawMaterialPurchaseAnalysisByDate(@Param("startDate") String startDate, @Param("endDate") String endDate); |
| | | |
| | | int selectProductCountByTypeAndDate(@Param("type") Integer type, @Param("startDate") LocalDateTime startDate, @Param("endDate") LocalDateTime endDate); |
| | | |
| | | BigDecimal selectRawMaterialExpense(); |
| | |
| | | # å¼åç¯å¢é
ç½® |
| | | server: |
| | | # æå¡å¨çHTTP端å£ï¼é»è®¤ä¸º8080 |
| | | port: 7006 |
| | | port: 7005 |
| | | servlet: |
| | | # åºç¨ç访é®è·¯å¾ |
| | | context-path: / |
| | |
| | | and dm.maintenance_actually_time < date_add(str_to_date(#{deviceMaintenanceDto.maintenanceActuallyTime}, '%Y-%m-%d'), interval 1 day) |
| | | </if> |
| | | </where> |
| | | ORDER BY dm.create_time DESC |
| | | </select> |
| | | <select id="detailById" resultType="com.ruoyi.device.vo.DeviceMaintenanceVo"> |
| | | select dm.id, |
| | |
| | | GROUP BY p.id, p.product_name |
| | | </select> |
| | | |
| | | <select id="productTurnoverDaysByDate" resultType="com.ruoyi.dto.MapDto"> |
| | | SELECT p.product_name AS name, |
| | | DATEDIFF(IFNULL(MAX(sor.create_time), NOW()), MAX(sir.create_time)) AS value |
| | | FROM product p |
| | | JOIN product_model pm ON p.id = pm.product_id |
| | | JOIN stock_in_record sir ON pm.id = sir.product_model_id |
| | | AND sir.create_time >= #{startDate} |
| | | AND sir.create_time <= #{endDate} |
| | | LEFT JOIN stock_out_record sor ON pm.id = sor.product_model_id |
| | | GROUP BY p.id, p.product_name |
| | | </select> |
| | | |
| | | <select id="selectPurchaseCategoryDistribution" resultType="com.ruoyi.dto.MapDto"> |
| | | SELECT p2.product_name AS name, |
| | | COUNT(DISTINCT slp.id) AS value |
| | | FROM sales_ledger_product slp |
| | | LEFT JOIN product p ON p.id = slp.product_category |
| | | LEFT JOIN product p2 ON p2.id = p.parent_id |
| | | WHERE slp.type = 2 |
| | | AND p.parent_id IS NOT NULL |
| | | GROUP BY p2.product_name |
| | | ORDER BY value DESC |
| | | </select> |
| | | |
| | | </mapper> |
| | |
| | | # GROUP BY DATE_FORMAT(a.issue_date, '%Y-%m') |
| | | </select> |
| | | |
| | | <select id="listVatDetail" resultType="com.ruoyi.purchase.dto.VatDto"> |
| | | SELECT * |
| | | FROM ( |
| | | -- è¿é¡¹ç¨æç»ï¼éè´è®¢åï¼ |
| | | SELECT |
| | | pl.purchase_contract_number AS invoiceNo, |
| | | pl.sales_contract_no AS salesContractNo, |
| | | pl.supplier_name AS supplierName, |
| | | NULL AS customerName, |
| | | 'è¿é¡¹' AS orderType, |
| | | pl.entry_date AS invoiceDate, |
| | | slp.tax_rate AS taxRate, |
| | | ROUND(SUM(slp.tax_inclusive_total_price - slp.tax_exclusive_total_price), 2) AS jTaxAmount, |
| | | 0 AS xTaxAmount, |
| | | ROUND(SUM(slp.tax_inclusive_total_price - slp.tax_exclusive_total_price), 2) AS taxAmount |
| | | FROM sales_ledger_product slp |
| | | LEFT JOIN purchase_ledger pl ON pl.id = slp.sales_ledger_id |
| | | WHERE slp.type = 2 |
| | | AND slp.tax_rate IS NOT NULL |
| | | AND slp.tax_rate > 0 |
| | | GROUP BY pl.id |
| | | |
| | | UNION ALL |
| | | |
| | | -- éé¡¹ç¨æç»ï¼éå®è®¢åï¼ |
| | | SELECT |
| | | sl.sales_contract_no AS invoiceNo, |
| | | sl.sales_contract_no AS salesContractNo, |
| | | NULL AS supplierName, |
| | | sl.customer_name AS customerName, |
| | | 'é项' AS orderType, |
| | | sl.entry_date AS invoiceDate, |
| | | slp.tax_rate AS taxRate, |
| | | 0 AS jTaxAmount, |
| | | ROUND(SUM(slp.tax_inclusive_total_price - slp.tax_exclusive_total_price), 2) AS xTaxAmount, |
| | | ROUND(SUM(slp.tax_inclusive_total_price - slp.tax_exclusive_total_price), 2) AS taxAmount |
| | | FROM sales_ledger_product slp |
| | | LEFT JOIN sales_ledger sl ON sl.id = slp.sales_ledger_id |
| | | WHERE slp.type = 1 |
| | | AND slp.tax_rate IS NOT NULL |
| | | AND slp.tax_rate > 0 |
| | | GROUP BY sl.id |
| | | ) a |
| | | <where> |
| | | <if test="month != null and month != ''"> |
| | | AND DATE_FORMAT(a.invoiceDate, '%Y-%m') = #{month} |
| | | </if> |
| | | </where> |
| | | ORDER BY a.invoiceDate DESC |
| | | </select> |
| | | |
| | | </mapper> |
| | |
| | | LIMIT 5 |
| | | </select> |
| | | |
| | | <select id="selectProductSalesAnalysisByDate" resultType="java.util.Map"> |
| | | SELECT |
| | | product_category as name, |
| | | SUM( tax_inclusive_total_price ) AS value |
| | | FROM |
| | | sales_ledger_product |
| | | WHERE |
| | | type = 1 |
| | | AND register_date >= #{startDate} |
| | | AND register_date <= #{endDate} |
| | | GROUP BY |
| | | product_category |
| | | ORDER BY |
| | | value DESC |
| | | LIMIT 5 |
| | | </select> |
| | | |
| | | <select id="selectRawMaterialPurchaseAnalysis" resultType="java.util.Map"> |
| | | SELECT |
| | | pr.product_name AS name, |
| | |
| | | LIMIT 5 |
| | | </select> |
| | | |
| | | <select id="selectRawMaterialPurchaseAnalysisByDate" resultType="java.util.Map"> |
| | | SELECT |
| | | pr.product_name AS name, |
| | | SUM( slp.tax_inclusive_total_price ) AS value |
| | | FROM |
| | | sales_ledger_product slp |
| | | JOIN product pr ON slp.product_id = pr.id |
| | | WHERE |
| | | slp.type = 2 |
| | | AND slp.register_date >= #{startDate} |
| | | AND slp.register_date <= #{endDate} |
| | | AND pr.parent_id = ( SELECT id FROM product WHERE product_name = 'åææ' ) |
| | | GROUP BY |
| | | pr.id, |
| | | pr.product_name |
| | | ORDER BY |
| | | value DESC |
| | | LIMIT 5 |
| | | </select> |
| | | |
| | | <select id="selectProductCountByTypeAndDate" resultType="int"> |
| | | SELECT IFNULL(COUNT(*), 0) |
| | | FROM sales_ledger_product |