From d5470a1898a9b44b46db52df6496d0381f651a07 Mon Sep 17 00:00:00 2001 From: liuxiaoxu <1793812695@qq.com> Date: Thu, 20 Feb 2025 09:33:24 +0800 Subject: [PATCH] =?UTF-8?q?[feat]=20=E5=94=AE=E5=90=8E=E7=AE=A1=E7=90=86?= =?UTF-8?q?=20=E6=8C=89=E7=85=A7=E4=B8=87=E6=9D=90=E8=A6=81=E6=B1=82?= =?UTF-8?q?=EF=BC=8C=E5=9F=BA=E7=A1=80=E8=B5=84=E6=96=99=E8=AF=B7=E8=B4=AD?= =?UTF-8?q?=E5=8D=95=E6=96=B0=E5=A2=9E=E5=AF=BC=E5=87=BA=E5=8A=9F=E8=83=BD?= =?UTF-8?q?=EF=BC=8C=E6=94=AF=E6=8C=81=E9=83=A8=E5=88=86=E8=A1=8C=E5=92=8C?= =?UTF-8?q?=E5=85=A8=E9=83=A8=E8=A1=8C=E5=AF=BC=E5=87=BA=EF=BC=8C=E5=AF=BC?= =?UTF-8?q?=E5=87=BA=E6=9B=B4=E5=A4=9A=E6=95=B0=E6=8D=AE=20=E6=96=B0?= =?UTF-8?q?=E5=A2=9E=E5=AF=BC=E5=87=BA=E6=89=80=E6=9C=89=E5=92=8C=E9=80=89?= =?UTF-8?q?=E6=8B=A9=E5=AF=BC=E5=87=BA=E5=90=8E=E7=AB=AF=E6=8E=A5=E5=8F=A3?= =?UTF-8?q?=20=E6=96=B0=E5=A2=9E=20=E5=AF=BC=E5=87=BA=E5=9F=BA=E7=A1=80?= =?UTF-8?q?=E8=B5=84=E6=96=99=E8=AF=B7=E8=B4=AD=E5=8D=95=E6=98=8E=E7=BB=86?= =?UTF-8?q?=E6=96=B9=E6=B3=95=20=E6=96=B0=E5=A2=9E=E6=A0=B9=E6=8D=AE?= =?UTF-8?q?=E5=9F=BA=E7=A1=80=E8=B5=84=E6=96=99=E8=AF=B7=E8=B4=AD=E5=8D=95?= =?UTF-8?q?=E9=9B=86=E5=90=88=E6=96=B9=E6=B3=95=20=E6=96=B0=E5=A2=9E?= =?UTF-8?q?=E5=AF=BC=E5=87=BA=E5=9F=BA=E7=A1=80=E8=B5=84=E6=96=99=E8=AF=B7?= =?UTF-8?q?=E8=B4=AD=E5=8D=95=E6=98=8E=E7=BB=86=20=E4=BF=AE=E5=A4=8D?= =?UTF-8?q?=EF=BC=8C=E8=AF=B7=E8=B4=AD=E5=8D=95=E5=88=86=E9=A1=B5=E6=9F=A5?= =?UTF-8?q?=E8=AF=A2=E5=A4=9A=E4=BD=99=E7=9A=84=E5=BC=82=E5=B8=B8=E6=8A=9B?= =?UTF-8?q?=E5=87=BA=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../BaseRequisitioningOrderController.java | 23 +++- .../Vo/ExportBaseRequisitioningOrderVo.java | 118 ++++++++++++++++++ .../BaseRequisitioningOrderChildMapper.java | 5 + .../mapper/BaseRequisitioningOrderMapper.java | 5 + .../service/IBaseExpenseAccountService.java | 2 +- .../IBaseRequisitioningOrderService.java | 18 ++- .../impl/BaseExpenseAccountServiceImpl.java | 2 +- .../BaseRequisitioningOrderServiceImpl.java | 78 +++++++++++- .../BaseRequisitioningOrderChildMapper.xml | 8 ++ .../system/BaseRequisitioningOrderMapper.xml | 9 ++ .../system/requisitioning/requisitioning.html | 27 ++++ 11 files changed, 287 insertions(+), 8 deletions(-) create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/system/domain/Vo/ExportBaseRequisitioningOrderVo.java diff --git a/ruoyi-admin/src/main/java/com/ruoyi/system/controller/BaseRequisitioningOrderController.java b/ruoyi-admin/src/main/java/com/ruoyi/system/controller/BaseRequisitioningOrderController.java index d692f14d..aeb70efe 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/system/controller/BaseRequisitioningOrderController.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/system/controller/BaseRequisitioningOrderController.java @@ -20,8 +20,11 @@ import com.ruoyi.purchase.service.IPurchasePlanService; import com.ruoyi.system.domain.*; import com.ruoyi.system.domain.Vo.BaseExpenseAccountVo; import com.ruoyi.system.domain.Vo.BaseRequisitioningOrderVo; +import com.ruoyi.system.domain.Vo.ExportBaseRequisitioningOrderVo; import com.ruoyi.system.mapper.*; import com.ruoyi.system.service.*; +import com.ruoyi.warehouse.domain.VO.ExportWarehouseStorageOrderVo; +import com.ruoyi.warehouse.domain.WarehouseStorageOrder; import org.activiti.engine.RuntimeService; import org.activiti.engine.TaskService; import org.activiti.engine.runtime.ProcessInstance; @@ -31,6 +34,7 @@ import org.apache.shiro.authz.annotation.RequiresPermissions; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.ModelMap; +import org.springframework.util.StringUtils; import org.springframework.web.bind.annotation.*; import com.ruoyi.common.annotation.Log; import com.ruoyi.common.enums.BusinessType; @@ -123,10 +127,21 @@ public class BaseRequisitioningOrderController extends BaseController @Log(title = "请购单", businessType = BusinessType.EXPORT) @PostMapping("/export") @ResponseBody - public AjaxResult export(BaseRequisitioningOrderVo baseRequisitioningOrder) throws Exception { - List list = baseRequisitioningOrderService.selectBaseRequisitioningOrderList(baseRequisitioningOrder); - ExcelUtil util = new ExcelUtil(BaseRequisitioningOrderVo.class); - return util.exportExcel(list, "请购单数据"); + public AjaxResult export(BaseRequisitioningOrderVo baseRequisitioningOrder,String ids){ + + if (StringUtils.isEmpty(ids)){ + List list = baseRequisitioningOrderService.selectBaseRequisitioningOrderListByObject(baseRequisitioningOrder); + List exportWarehouseStorageOrderVos = baseRequisitioningOrderService.exportRequisitioningOrderList(list); + ExcelUtil util = new ExcelUtil(ExportBaseRequisitioningOrderVo.class); + return util.exportExcel(exportWarehouseStorageOrderVos, "请购单数据"); + }else { + String[] requisitioningCodes = ids.split(","); + List list = baseRequisitioningOrderService.selectBaseRequisitioningOrderListByCodes(requisitioningCodes); + List exportWarehouseStorageOrderVos = baseRequisitioningOrderService.exportRequisitioningOrderList(list); + ExcelUtil util = new ExcelUtil(ExportBaseRequisitioningOrderVo.class); + return util.exportExcel(exportWarehouseStorageOrderVos, "请购单数据"); + } + } /** * 新增请购单 diff --git a/ruoyi-admin/src/main/java/com/ruoyi/system/domain/Vo/ExportBaseRequisitioningOrderVo.java b/ruoyi-admin/src/main/java/com/ruoyi/system/domain/Vo/ExportBaseRequisitioningOrderVo.java new file mode 100644 index 00000000..76952ba3 --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/system/domain/Vo/ExportBaseRequisitioningOrderVo.java @@ -0,0 +1,118 @@ +package com.ruoyi.system.domain.Vo; + +import com.ruoyi.common.annotation.Excel; +import lombok.Data; + +import java.math.BigDecimal; + +/** +* 导出请购单吗明细 +* */ +@Data +public class ExportBaseRequisitioningOrderVo { + + + + + /** 请购单编号 */ + @Excel(name = "请购单编号") + private String requisitioningCode; + + /** 关联单号 */ + @Excel(name = "关联单号") + private String correlationCode; + + /** 请购状态 */ + @Excel(name = "请购状态",dictType = "sys_requisitioning_status") + private String requisitioningStatus; + + /** 请购部门 */ + @Excel(name = "请购部门") + private String deptName; + + /** 物料合计 */ + @Excel(name = "物料合计") + private Integer materialAmount; + + /** 数量总计 */ + @Excel(name = "数量总计") + private Long materialSum; + + + /** 不含税总价(RMB) */ + @Excel(name = "不含税总价(RMB)") + private BigDecimal noRmbSum; + + /** 预估总价(RMB) */ + @Excel(name = "预估总价(RMB)") + private BigDecimal rmbSum; + + private BigDecimal estimatePrice; + + /** 申请人 */ + @Excel(name = "申请人") + private String applyUser; + + /** 使用状态 */ + @Excel(name = "使用状态",dictType = "useStatus") + private String useStatus; + + /** 审核状态 */ + @Excel(name = "审核状态",dictType = "auditStatus") + private String auditStatus; + + + + /** 料号 */ + @Excel(name = "料号") + private String materialCode; + + /** 物料的名称 */ + @Excel(name = "物料的名称") + private String materialName; + + /** 物料的型号 */ + @Excel(name = "物料的型号") + private String materialModel; + + /** 加工方式*/ + @Excel(name = "加工方式",dictType = "processMethod") + private String processMethod; + + /** 物料的品牌 */ + @Excel(name = "物料的品牌") + private String brand; + + /** 物料的单位 */ + @Excel(name = "物料的单位") + private String unit; + + /** 物料的描述 */ + @Excel(name = "物料的描述") + private String describe; + + @Excel(name = "入库部门",dictType = "warehouseDept") + private String warehouseDept; + + /** 物料的数量 */ + @Excel(name = "物料的数量") + private Integer materialNum; + + /** 物料的不含税单价(RMB) */ + @Excel(name = "物料的不含税单价(RMB)") + private BigDecimal materialRmb; + + /** 物料的含税单价(RMB) */ + @Excel(name = "物料的含税单价(RMB)") + private BigDecimal materialNoRmb; + + /** 物料的含税总价(RMB) */ + @Excel(name = "物料的含税总价(RMB)") + private BigDecimal materialNoRmbSum; + + /** 物料的不含税总价(RMB) */ + @Excel(name = "物料的不含税总价(RMB)") + private BigDecimal materialRmbSum; + + +} diff --git a/ruoyi-admin/src/main/java/com/ruoyi/system/mapper/BaseRequisitioningOrderChildMapper.java b/ruoyi-admin/src/main/java/com/ruoyi/system/mapper/BaseRequisitioningOrderChildMapper.java index 3c9e6d66..4e633024 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/system/mapper/BaseRequisitioningOrderChildMapper.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/system/mapper/BaseRequisitioningOrderChildMapper.java @@ -119,4 +119,9 @@ public interface BaseRequisitioningOrderChildMapper * 检查请购单子表是否引用了物料 * */ int checkMaterialIsReferencedByRequisitioningOrderChild(String materialNo); + + /** + * 根据请购单号批量查询请购单子表 + * */ + List selectBaseRequisitioningOrderChildByCodeList(List collectRequisitioningCodes); } diff --git a/ruoyi-admin/src/main/java/com/ruoyi/system/mapper/BaseRequisitioningOrderMapper.java b/ruoyi-admin/src/main/java/com/ruoyi/system/mapper/BaseRequisitioningOrderMapper.java index 26692b12..b9d4b47f 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/system/mapper/BaseRequisitioningOrderMapper.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/system/mapper/BaseRequisitioningOrderMapper.java @@ -119,4 +119,9 @@ public interface BaseRequisitioningOrderMapper */ List selectBaseRequisitioningOrderByIds(String[] ids); + + /** + * 根据编码批量查询请购单 + * */ + List selectBaseRequisitioningOrderListByCodes(String[] requisitioningCodes); } diff --git a/ruoyi-admin/src/main/java/com/ruoyi/system/service/IBaseExpenseAccountService.java b/ruoyi-admin/src/main/java/com/ruoyi/system/service/IBaseExpenseAccountService.java index ee994539..c6b0c658 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/system/service/IBaseExpenseAccountService.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/system/service/IBaseExpenseAccountService.java @@ -97,5 +97,5 @@ public interface IBaseExpenseAccountService BaseExpenseAccount selectBaseExpenseAccountByCode(String expenseCode); // 获取当前登录名下可看用户列表 - Set userLimitedList(Set roleKeys, SysUser curUser) throws Exception; + Set userLimitedList(Set roleKeys, SysUser curUser); } diff --git a/ruoyi-admin/src/main/java/com/ruoyi/system/service/IBaseRequisitioningOrderService.java b/ruoyi-admin/src/main/java/com/ruoyi/system/service/IBaseRequisitioningOrderService.java index f339ff49..20f6df11 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/system/service/IBaseRequisitioningOrderService.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/system/service/IBaseRequisitioningOrderService.java @@ -4,6 +4,7 @@ import java.util.List; import com.ruoyi.system.domain.BaseRequisitioningOrder; import com.ruoyi.system.domain.SysSalesOrder; import com.ruoyi.system.domain.Vo.BaseRequisitioningOrderVo; +import com.ruoyi.system.domain.Vo.ExportBaseRequisitioningOrderVo; import org.activiti.engine.runtime.ProcessInstance; import org.springframework.transaction.annotation.Transactional; @@ -30,7 +31,7 @@ public interface IBaseRequisitioningOrderService * @return 请购单集合 */ - List selectBaseRequisitioningOrderList(BaseRequisitioningOrderVo baseRequisitioningOrderVo) throws Exception; + List selectBaseRequisitioningOrderList(BaseRequisitioningOrderVo baseRequisitioningOrderVo); /** * 新增请购单 @@ -107,4 +108,19 @@ public interface IBaseRequisitioningOrderService * 请购单审核通过后生成采购计划 * */ void generatePurchasePlan(BaseRequisitioningOrder baseRequisitioningOrder); + + /** + * 导出请购单明细 + * */ + List exportRequisitioningOrderList(List list); + + /** + * 根据请购单号查询请购单明细 + * */ + List selectBaseRequisitioningOrderListByCodes(String[] requisitioningCodes); + + /** + * 根据请购单对象查询请购单明细 + * */ + List selectBaseRequisitioningOrderListByObject(BaseRequisitioningOrderVo baseRequisitioningOrder); } diff --git a/ruoyi-admin/src/main/java/com/ruoyi/system/service/impl/BaseExpenseAccountServiceImpl.java b/ruoyi-admin/src/main/java/com/ruoyi/system/service/impl/BaseExpenseAccountServiceImpl.java index 79bc749e..89a2ea15 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/system/service/impl/BaseExpenseAccountServiceImpl.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/system/service/impl/BaseExpenseAccountServiceImpl.java @@ -532,7 +532,7 @@ public class BaseExpenseAccountServiceImpl implements IBaseExpenseAccountService // 获取当前登录名下可看用户列表 @Override - public Set userLimitedList(Set roleKeys, SysUser curUser) throws Exception { + public Set userLimitedList(Set roleKeys, SysUser curUser){ List sysUserlist = sysUserService.selectUserAll(); diff --git a/ruoyi-admin/src/main/java/com/ruoyi/system/service/impl/BaseRequisitioningOrderServiceImpl.java b/ruoyi-admin/src/main/java/com/ruoyi/system/service/impl/BaseRequisitioningOrderServiceImpl.java index d3a1d6bb..268bdf70 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/system/service/impl/BaseRequisitioningOrderServiceImpl.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/system/service/impl/BaseRequisitioningOrderServiceImpl.java @@ -3,6 +3,7 @@ package com.ruoyi.system.service.impl; import java.math.BigDecimal; import java.math.RoundingMode; import java.util.*; +import java.util.function.Function; import java.util.stream.Collectors; import com.github.pagehelper.Page; @@ -28,6 +29,7 @@ import com.ruoyi.purchase.service.IPurchasePlanService; import com.ruoyi.system.domain.BaseRequisitioningOrderChild; import com.ruoyi.system.domain.Vo.BaseExpenseAccountVo; import com.ruoyi.system.domain.Vo.BaseRequisitioningOrderVo; +import com.ruoyi.system.domain.Vo.ExportBaseRequisitioningOrderVo; import com.ruoyi.system.mapper.BaseRequisitioningOrderChildMapper; import com.ruoyi.system.mapper.SysUserMapper; import com.ruoyi.system.service.*; @@ -124,7 +126,7 @@ public class BaseRequisitioningOrderServiceImpl implements IBaseRequisitioningOr * @return 请购单 */ @Override - public List selectBaseRequisitioningOrderList(BaseRequisitioningOrderVo baseRequisitioningOrderVo1) throws Exception { + public List selectBaseRequisitioningOrderList(BaseRequisitioningOrderVo baseRequisitioningOrderVo1){ SysUser curUser = ShiroUtils.getSysUser(); Long userId = curUser.getUserId(); Set roleKeys = roleService.selectRoleKeys(userId); @@ -205,6 +207,12 @@ public class BaseRequisitioningOrderServiceImpl implements IBaseRequisitioningOr return returnList; } + + @Override + public List selectBaseRequisitioningOrderListByObject(BaseRequisitioningOrderVo baseRequisitioningOrder) { + return baseRequisitioningOrderMapper.selectBaseRequisitioningOrderList(baseRequisitioningOrder); + } + /** * 新增请购单 * @@ -666,4 +674,72 @@ public class BaseRequisitioningOrderServiceImpl implements IBaseRequisitioningOr } } + + + @Override + public List selectBaseRequisitioningOrderListByCodes(String[] requisitioningCodes) { + return baseRequisitioningOrderMapper.selectBaseRequisitioningOrderListByCodes(requisitioningCodes); + } + + /** + * 导出请购单明细 + * */ + @Override + public List exportRequisitioningOrderList(List list) { + // 获取所有的请购单编号 + List collectRequisitioningCodes = list.stream() + .map(BaseRequisitioningOrderVo::getRequisitioningCode) + .collect(Collectors.toList()); + + // 根据请购单编号查询对应的物料详情列表 + List baseRequisitioningOrderChildList = baseRequisitioningOrderChildMapper.selectBaseRequisitioningOrderChildByCodeList(collectRequisitioningCodes); + + // 创建一个 BaseRequisitioningOrderVo 的 Map,键为请购单编号 + Map baseRequisitioningOrderVoMap = list.stream() + .collect(Collectors.toMap(BaseRequisitioningOrderVo::getRequisitioningCode, Function.identity(), (existing, replacement) -> existing)); + + // 初始化导出列表 + List exportBaseRequisitioningOrderVos = new ArrayList<>(); + + for (BaseRequisitioningOrderChild child : baseRequisitioningOrderChildList) { + ExportBaseRequisitioningOrderVo exportVo = new ExportBaseRequisitioningOrderVo(); + + // 从 BaseRequisitioningOrderChild 填充数据 + exportVo.setMaterialCode(child.getMaterialCode()); + exportVo.setMaterialName(child.getMaterialName()); + exportVo.setMaterialModel(child.getMaterialModel()); + exportVo.setProcessMethod(child.getProcessMethod()); + exportVo.setBrand(child.getBrand()); + exportVo.setUnit(child.getUnit()); + exportVo.setDescribe(child.getDescribe()); + exportVo.setWarehouseDept(child.getWarehouseDept()); + exportVo.setMaterialNum(child.getMaterialNum()); + exportVo.setMaterialRmb(child.getMaterialRmb()); + exportVo.setMaterialNoRmb(child.getMaterialNoRmb()); + exportVo.setMaterialNoRmbSum(child.getMaterialNoRmbSum()); + exportVo.setMaterialRmbSum(child.getMaterialRmbSum()); + + // 从 BaseRequisitioningOrderVo 填充数据,通过请购单编号进行关联 + BaseRequisitioningOrderVo order = baseRequisitioningOrderVoMap.get(child.getRequisitioningCode()); + if (order != null) { + exportVo.setRequisitioningCode(order.getRequisitioningCode()); + exportVo.setCorrelationCode(order.getCorrelationCode()); + exportVo.setRequisitioningStatus(order.getRequisitioningStatus()); + exportVo.setDeptName(order.getDeptName()); + exportVo.setMaterialAmount(order.getMaterialAmount()); + exportVo.setMaterialSum(order.getMaterialSum()); + exportVo.setNoRmbSum(order.getNoRmbSum()); + exportVo.setRmbSum(order.getRmbSum()); + exportVo.setEstimatePrice(order.getEstimatePrice()); + exportVo.setApplyUser(order.getApplyUser()); + exportVo.setUseStatus(order.getUseStatus()); + exportVo.setAuditStatus(order.getAuditStatus()); + } + + // 添加到结果列表 + exportBaseRequisitioningOrderVos.add(exportVo); + } + + return exportBaseRequisitioningOrderVos; + } } diff --git a/ruoyi-admin/src/main/resources/mapper/system/BaseRequisitioningOrderChildMapper.xml b/ruoyi-admin/src/main/resources/mapper/system/BaseRequisitioningOrderChildMapper.xml index 0d0fa7e2..ba2a756a 100644 --- a/ruoyi-admin/src/main/resources/mapper/system/BaseRequisitioningOrderChildMapper.xml +++ b/ruoyi-admin/src/main/resources/mapper/system/BaseRequisitioningOrderChildMapper.xml @@ -75,6 +75,14 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" select count(1) from base_requisitioning_order_child where material_code = #{materialCode} + + insert into base_requisitioning_order_child diff --git a/ruoyi-admin/src/main/resources/mapper/system/BaseRequisitioningOrderMapper.xml b/ruoyi-admin/src/main/resources/mapper/system/BaseRequisitioningOrderMapper.xml index 54b0021b..9051c710 100644 --- a/ruoyi-admin/src/main/resources/mapper/system/BaseRequisitioningOrderMapper.xml +++ b/ruoyi-admin/src/main/resources/mapper/system/BaseRequisitioningOrderMapper.xml @@ -105,6 +105,15 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" #{id} + + insert into base_requisitioning_order diff --git a/ruoyi-admin/src/main/resources/templates/system/requisitioning/requisitioning.html b/ruoyi-admin/src/main/resources/templates/system/requisitioning/requisitioning.html index ba7e11f6..48f27a70 100644 --- a/ruoyi-admin/src/main/resources/templates/system/requisitioning/requisitioning.html +++ b/ruoyi-admin/src/main/resources/templates/system/requisitioning/requisitioning.html @@ -66,6 +66,9 @@ 添加 + + 导出 +
@@ -257,6 +260,30 @@ }; $.table.init(options); }); + + // 导出 + function exportExcel() { + var ids = $.table.selectColumns("requisitioningCode"); + var dataParam = $("#formId").serializeArray(); + + let tipMsg = "确定导出当前所有数据吗?"; + if ($.common.isNotEmpty(ids)) { + tipMsg = `确定导出 ${ids} 数据吗?`; + dataParam.push({ "name": "ids", "value": ids }); + } + $.modal.confirm(tipMsg, function () { + $.modal.loading("正在导出数据,请稍后..."); + $.post( prefix + "/export", dataParam, function (result) { + if (result.code === web_status.SUCCESS) { + window.location.href = ctx + "common/download?fileName="+ encodeURI(result.msg) + "&delete=" + true; + } else { + $.modal.alertError(result.msg); + } + $.modal.closeLoading(); + }); + }); + } + \ No newline at end of file