Web 毕设篇-适合小白、初级入门练手的 Spring Boot Web 毕业设计项目:药品进销存信息管理系统(前后端源码 + 数据库 sql 脚本)

🔥博客主页: 【小扳_-CSDN博客】
❤感谢大家点赞👍收藏⭐评论✍

文章目录

        1.0 项目介绍

        1.1 项目功能

        2.0 用户登录功能

        3.0 首页界面

        4.0 供应商管理功能

        5.0 药品管理功能

        6.0 采购记录管理功能

        7.0 销售记录管理功能

        8.0 退货记录管理功能

        9.0 库存变动管理功能

        10.0 SQL 数据库设计


        1.0 项目介绍

        开发工具:IDEA、VScode

        服务器:Tomcat, JDK 17

        项目构建:maven

        数据库:mysql 8.0

系统用户前台和管理后台两部分,项目采用前后端分离

        前端技术:vue3 + elementUI

        服务端技术:springboot + mybatis + redis + mysql

        1.1 项目功能


后台功能:

        1)登录、退出系统、首页

        2)供应商信息管理

                (1) 供应商信息管理:添加、修改、删除、查询等功能。

        3)药品管理

                (1) 药品管理:添加、修改、删除、查询等功能。

        4)采购登记管理

                (1) 采购登记管理:添加、修改、删除、查询等功能。

        5)销售记录管理

                (1) 销售记录管理:添加、修改、删除、查询等功能。

        6)退货记录管理

                (1) 退货记录管理:添加、修改、删除、查询等功能。

        7)库存变动管理

                (1) 库存变动管理:添加、修改、删除、查询等功能。

        8)系统管理

                用户信息管理

                        (1)用户信息管理:添加、修改、删除、查询等功能。

                角色管理

                        (2)角色信息管理:添加、修改、删除、查询等功能。

                菜单管理

                        (3)菜单信息管理:添加、修改、删除、查询等功能。

                日志管理

                        (4)日志信息管理:添加、修改、删除、查询等功能。

        9)系统监控

                        查看在先用户、设置定时任务、数据监控、缓存监控、查看缓存列表等。

        10)权限管理

                (1) 角色信息管理:添加、修改、删除、分配权限等功能。

                (2) 资源信息管理:添加、修改、删除等功能。

注意:不一定非要完全符合开发环境,有稍微的差别也是可以开发的。

         若需要项目完整源码,可以在 CSDN 私信给我,我每天都有查看消息的,感谢大家支持,希望可以帮助到大家!

        2.0 用户登录功能

        用户根据正确的用户名、密码且通过正确的校验码进行登录。

        实现了登录校验,还有用户注册功能:

        用到了 Spring Security 框架来实现登录、校验、验证等功能。 

相关的部分源码:

@RestController
public class SysLoginController
{
    @Autowired
    private SysLoginService loginService;
 
    @Autowired
    private ISysMenuService menuService;
 
    @Autowired
    private SysPermissionService permissionService;
 
    /**
     * 登录方法
     * 
     * @param loginBody 登录信息
     * @return 结果
     */
    @PostMapping("/login")
    public AjaxResult login(@RequestBody LoginBody loginBody)
    {
        AjaxResult ajax = AjaxResult.success();
        // 生成令牌
        String token = loginService.login(loginBody.getUsername(), loginBody.getPassword(), loginBody.getCode(),
                loginBody.getUuid());
        ajax.put(Constants.TOKEN, token);
        return ajax;
    }
 
    /**
     * 获取用户信息
     * 
     * @return 用户信息
     */
    @GetMapping("getInfo")
    public AjaxResult getInfo()
    {
        SysUser user = SecurityUtils.getLoginUser().getUser();
        // 角色集合
        Set<String> roles = permissionService.getRolePermission(user);
        // 权限集合
        Set<String> permissions = permissionService.getMenuPermission(user);
        AjaxResult ajax = AjaxResult.success();
        ajax.put("user", user);
        ajax.put("roles", roles);
        ajax.put("permissions", permissions);
        return ajax;
    }
 
    /**
     * 获取路由信息
     * 
     * @return 路由信息
     */
    @GetMapping("getRouters")
    public AjaxResult getRouters()
    {
        Long userId = SecurityUtils.getUserId();
        List<SysMenu> menus = menuService.selectMenuTreeByUserId(userId);
        return AjaxResult.success(menuService.buildMenus(menus));
    }
}
    public String login(String username, String password, String code, String uuid)
    {
        // 验证码校验
        validateCaptcha(username, code, uuid);
        // 登录前置校验
        loginPreCheck(username, password);
        // 用户验证
        Authentication authentication = null;
        try
        {
            UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(username, password);
            AuthenticationContextHolder.setContext(authenticationToken);
            // 该方法会去调用UserDetailsServiceImpl.loadUserByUsername
            authentication = authenticationManager.authenticate(authenticationToken);
        }
        catch (Exception e)
        {
            if (e instanceof BadCredentialsException)
            {
                AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match")));
                throw new UserPasswordNotMatchException();
            }
            else
            {
                AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, e.getMessage()));
                throw new ServiceException(e.getMessage());
            }
        }
        finally
        {
            AuthenticationContextHolder.clearContext();
        }
        AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success")));
        LoginUser loginUser = (LoginUser) authentication.getPrincipal();
        recordLoginInfo(loginUser.getUserId());
        // 生成token
        return tokenService.createToken(loginUser);
    }

        3.0 首页界面

        统计相关药品的信息,使用柱状图和圆饼图等展示出来,会更加直观。

相关的前端源码:

<template>
  <div class="statistics">
    <!-- <h2 class="title">药品进销存统计信息</h2> -->
    <div class="chart-container">
      <div ref="barChart" class="chart"></div>
      <div ref="pieChart" class="chart"></div>
      <div ref="lineChart" class="chart"></div>
      <div ref="radarChart" class="chart"></div>
    </div>
  </div>
</template>

<script setup>
import * as echarts from 'echarts';
import { onMounted, ref } from 'vue';

const barChart = ref(null);
const pieChart = ref(null);
const lineChart = ref(null);
const radarChart = ref(null);

onMounted(() => {
  fetchAndInitCharts();
});

async function fetchAndInitCharts() {
  const salesData = {
    categories: ['阿司匹林', '布洛芬', '对乙酰氨基酚', '盐酸昂丹司琼注射液', '盐酸昂丹司琼注射液'],
    values: [120, 200, 150, 80, 70]
  };

  const inventoryData = [
    { value: 335, name: '阿司匹林' },
    { value: 310, name: '布洛芬' },
    { value: 234, name: '对乙酰氨基酚' },
    { value: 135, name: '盐酸昂丹司琼注射液' },
    { value: 1548, name: '盐酸昂丹司琼注射液' }
  ];

  const trendData = {
    categories: ['1月', '2月', '3月', '4月', '5月', '6月'],
    values: [120, 200, 150, 80, 70, 100]
  };

  const radarData = {
    indicators: [
      { name: '质量', max: 100 },
      { name: '价格', max: 100 },
      { name: '销量', max: 100 },
      { name: '库存', max: 100 },
      { name: '满意度', max: 100 }
    ],
    series: [
      {
        value: [80, 60, 70, 50, 90],
        name: '阿司匹林'
      }
    ]
  };

  initBarChart(salesData);
  initPieChart(inventoryData);
  initLineChart(trendData);
  initRadarChart(radarData);
}

function initBarChart(data) {
  const chart = echarts.init(barChart.value);
  const option = {
    title: {
      text: '药品销售量统计',
      left: 'center',
      textStyle: {
        color: '#111711', // 修改字体颜色
        fontSize: 24
      }
    },
    tooltip: {
      trigger: 'axis',
      axisPointer: {
        type: 'shadow'
      }
    },
    xAxis: {
      type: 'category',
      data: data.categories,
      axisLabel: {
        interval: 0,
        rotate: 30,
        color: '#111711' // 修改字体颜色
      },
      axisLine: {
        lineStyle: {
          color: '#fff'
        }
      }
    },
    yAxis: {
      type: 'value',
      axisLabel: {
        color: '#111711' // 修改字体颜色
      },
      axisLine: {
        lineStyle: {
          color: '#fff'
        }
      }
    },
    series: [{
      data: data.values,
      type: 'bar',
      itemStyle: {
        color: '#6A5ACD' // 更改颜色为更深的紫色
      }
    }],
    backgroundColor: 'transparent' // 设置背景色为透明
  };
  chart.setOption(option);
}

function initPieChart(data) {
  const chart = echarts.init(pieChart.value);
  const option = {
    title: {
      text: '药品库存比例',
      left: 'center',
      textStyle: {
        color: '#111711', // 修改字体颜色
        fontSize: 24
      }
    },
    tooltip: {
      trigger: 'item'
    },
    legend: {
      orient: 'vertical',
      left: 'left',
      textStyle: {
        color: '#111711' // 修改字体颜色
      }
    },
    series: [{
      name: '药品库存',
      type: 'pie',
      radius: '50%',
      data: data,
      emphasis: {
        itemStyle: {
          shadowBlur: 10,
          shadowOffsetX: 0,
          shadowColor: 'rgba(0, 0, 0, 0.5)'
        }
      },
      itemStyle: {
        color: (params) => {
          const colorList = ['#FF69B4', '#FFD700', '#32CD32', '#1E90FF', '#FF6347']; // 更改颜色为更青春的色调
          return colorList[params.dataIndex];
        }
      }
    }],
    backgroundColor: 'transparent' // 设置背景色为透明
  };
  chart.setOption(option);
}

function initLineChart(data) {
  const chart = echarts.init(lineChart.value);
  const option = {
    title: {
      text: '药品销售趋势',
      left: 'center',
      textStyle: {
        color: '#111711', // 修改字体颜色
        fontSize: 24
      }
    },
    tooltip: {
      trigger: 'axis'
    },
    xAxis: {
      type: 'category',
      data: data.categories,
      axisLabel: {
        color: '#111711' // 修改字体颜色
      },
      axisLine: {
        lineStyle: {
          color: '#fff'
        }
      }
    },
    yAxis: {
      type: 'value',
      axisLabel: {
        color: '#111711' // 修改字体颜色
      },
      axisLine: {
        lineStyle: {
          color: '#fff'
        }
      }
    },
    series: [{
      data: data.values,
      type: 'line',
      smooth: true,
      itemStyle: {
        color: '#FF69B4' // 更改颜色为粉红
      }
    }],
    backgroundColor: 'transparent' // 设置背景色为透明
  };
  chart.setOption(option);
}

function initRadarChart(data) {
  const chart = echarts.init(radarChart.value);
  const option = {
    title: {
      text: '药品综合评价',
      left: 'center',
      textStyle: {
        color: '#111711', // 修改字体颜色
        fontSize: 24
      }
    },
    tooltip: {
      trigger: 'item'
    },
    radar: {
      indicator: data.indicators,
      axisName: {
        color: '#111711' // 修改字体颜色
      },
      splitArea: {
        areaStyle: {
          color: ['#17273B', '#233B56']
        }
      }
    },
    series: [{
      name: '药品综合评价',
      type: 'radar',
      data: data.series,
      itemStyle: {
        color: '#FF69B4' // 更改颜色为粉红
      }
    }],
    backgroundColor: 'transparent' // 设置背景色为透明
  };
  chart.setOption(option);
}
</script>

<style scoped>
.statistics {
  padding: 40px;
  display: flex;
  flex-direction: column;
  align-items: center;
  background-color: #4DA3D4;
  background-image: url('../../assets/images/4.jpg'); /* 设置背景图 */
  background-size: cover; /* 使背景图覆盖整个容器 */
  background-position: center; /* 背景图居中 */
  color: #111711; /* 修改字体颜色 */
  min-height: 100vh;
}

.title {
  font-size: 36px;
  margin-bottom: 40px;
  color: #111711; /* 修改字体颜色 */
}

.chart-container {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(400px, 1fr));
  gap: 40px;
  width: 100%;
  max-width: 1400px;
}

.chart {
  width: 100%;
  height: 500px;
  border: 1px solid #ddd;
  box-shadow: 0 4px 8px rgba(0, 0, 0, 1);
  border-radius: 12px;
  overflow: hidden;
  background-color: transparent; /* 设置背景色为透明 */
}
</style>

        4.0 供应商管理功能

        上传图片使用了第三方接口:x-File-Storage 框架。

相关源码:

@RestController
@RequestMapping("/manage/suppliers")
public class SuppliersController extends BaseController
{
    @Autowired
    private ISuppliersService suppliersService;

    /**
     * 查询供应商信息列表
     */
    @PreAuthorize("@ss.hasPermi('manage:suppliers:list')")
    @GetMapping("/list")
    public TableDataInfo list(Suppliers suppliers)
    {
        startPage();
        List<Suppliers> list = suppliersService.selectSuppliersList(suppliers);
        return getDataTable(list);
    }

    /**
     * 导出供应商信息列表
     */
    @PreAuthorize("@ss.hasPermi('manage:suppliers:export')")
    @Log(title = "供应商信息", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    public void export(HttpServletResponse response, Suppliers suppliers)
    {
        List<Suppliers> list = suppliersService.selectSuppliersList(suppliers);
        ExcelUtil<Suppliers> util = new ExcelUtil<Suppliers>(Suppliers.class);
        util.exportExcel(response, list, "供应商信息数据");
    }

    /**
     * 获取供应商信息详细信息
     */
    @PreAuthorize("@ss.hasPermi('manage:suppliers:query')")
    @GetMapping(value = "/{supplierId}")
    public AjaxResult getInfo(@PathVariable("supplierId") Long supplierId)
    {
        return success(suppliersService.selectSuppliersBySupplierId(supplierId));
    }

    /**
     * 新增供应商信息
     */
    @PreAuthorize("@ss.hasPermi('manage:suppliers:add')")
    @Log(title = "供应商信息", businessType = BusinessType.INSERT)
    @PostMapping
    public AjaxResult add(@RequestBody Suppliers suppliers)
    {
        return toAjax(suppliersService.insertSuppliers(suppliers));
    }

    /**
     * 修改供应商信息
     */
    @PreAuthorize("@ss.hasPermi('manage:suppliers:edit')")
    @Log(title = "供应商信息", businessType = BusinessType.UPDATE)
    @PutMapping
    public AjaxResult edit(@RequestBody Suppliers suppliers)
    {
        return toAjax(suppliersService.updateSuppliers(suppliers));
    }

    /**
     * 删除供应商信息
     */
    @PreAuthorize("@ss.hasPermi('manage:suppliers:remove')")
    @Log(title = "供应商信息", businessType = BusinessType.DELETE)
	@DeleteMapping("/{supplierIds}")
    public AjaxResult remove(@PathVariable Long[] supplierIds)
    {
        return toAjax(suppliersService.deleteSuppliersBySupplierIds(supplierIds));
    }
}

        5.0 药品管理功能

相关源码:

@RestController
@RequestMapping("/manage/medicines")
public class MedicinesController extends BaseController
{
    @Autowired
    private IMedicinesService medicinesService;

    /**
     * 查询药品信息列表
     */
    @PreAuthorize("@ss.hasPermi('manage:medicines:list')")
    @GetMapping("/list")
    public TableDataInfo list(Medicines medicines)
    {
        startPage();
        List<Medicines> list = medicinesService.selectMedicinesList(medicines);
        return getDataTable(list);
    }

    /**
     * 导出药品信息列表
     */
    @PreAuthorize("@ss.hasPermi('manage:medicines:export')")
    @Log(title = "药品信息", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    public void export(HttpServletResponse response, Medicines medicines)
    {
        List<Medicines> list = medicinesService.selectMedicinesList(medicines);
        ExcelUtil<Medicines> util = new ExcelUtil<Medicines>(Medicines.class);
        util.exportExcel(response, list, "药品信息数据");
    }

    /**
     * 获取药品信息详细信息
     */
    @PreAuthorize("@ss.hasPermi('manage:medicines:query')")
    @GetMapping(value = "/{medicineId}")
    public AjaxResult getInfo(@PathVariable("medicineId") Long medicineId)
    {
        return success(medicinesService.selectMedicinesByMedicineId(medicineId));
    }

    /**
     * 新增药品信息
     */
    @PreAuthorize("@ss.hasPermi('manage:medicines:add')")
    @Log(title = "药品信息", businessType = BusinessType.INSERT)
    @PostMapping
    public AjaxResult add(@RequestBody Medicines medicines)
    {
        return toAjax(medicinesService.insertMedicines(medicines));
    }

    /**
     * 修改药品信息
     */
    @PreAuthorize("@ss.hasPermi('manage:medicines:edit')")
    @Log(title = "药品信息", businessType = BusinessType.UPDATE)
    @PutMapping
    public AjaxResult edit(@RequestBody Medicines medicines)
    {
        return toAjax(medicinesService.updateMedicines(medicines));
    }

    /**
     * 删除药品信息
     */
    @PreAuthorize("@ss.hasPermi('manage:medicines:remove')")
    @Log(title = "药品信息", businessType = BusinessType.DELETE)
	@DeleteMapping("/{medicineIds}")
    public AjaxResult remove(@PathVariable Long[] medicineIds)
    {
        return toAjax(medicinesService.deleteMedicinesByMedicineIds(medicineIds));
    }
}

        6.0 采购记录管理功能

        对药品进行采购。

相关源码:

@RestController
@RequestMapping("/manage/purchases")
public class PurchasesController extends BaseController
{
    @Autowired
    private IPurchasesService purchasesService;

    /**
     * 查询采购记录列表
     */
    @PreAuthorize("@ss.hasPermi('manage:purchases:list')")
    @GetMapping("/list")
    public TableDataInfo list(Purchases purchases)
    {
        startPage();
        List<Purchases> list = purchasesService.selectPurchasesList(purchases);
        return getDataTable(list);
    }

    /**
     * 导出采购记录列表
     */
    @PreAuthorize("@ss.hasPermi('manage:purchases:export')")
    @Log(title = "采购记录", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    public void export(HttpServletResponse response, Purchases purchases)
    {
        List<Purchases> list = purchasesService.selectPurchasesList(purchases);
        ExcelUtil<Purchases> util = new ExcelUtil<Purchases>(Purchases.class);
        util.exportExcel(response, list, "采购记录数据");
    }

    /**
     * 获取采购记录详细信息
     */
    @PreAuthorize("@ss.hasPermi('manage:purchases:query')")
    @GetMapping(value = "/{purchaseId}")
    public AjaxResult getInfo(@PathVariable("purchaseId") Long purchaseId)
    {
        return success(purchasesService.selectPurchasesByPurchaseId(purchaseId));
    }

    /**
     * 新增采购记录
     */
    @PreAuthorize("@ss.hasPermi('manage:purchases:add')")
    @Log(title = "采购记录", businessType = BusinessType.INSERT)
    @PostMapping
    public AjaxResult add(@RequestBody Purchases purchases)
    {
        return toAjax(purchasesService.insertPurchases(purchases));
    }

    /**
     * 修改采购记录
     */
    @PreAuthorize("@ss.hasPermi('manage:purchases:edit')")
    @Log(title = "采购记录", businessType = BusinessType.UPDATE)
    @PutMapping
    public AjaxResult edit(@RequestBody Purchases purchases)
    {
        return toAjax(purchasesService.updatePurchases(purchases));
    }

    /**
     * 删除采购记录
     */
    @PreAuthorize("@ss.hasPermi('manage:purchases:remove')")
    @Log(title = "采购记录", businessType = BusinessType.DELETE)
	@DeleteMapping("/{purchaseIds}")
    public AjaxResult remove(@PathVariable Long[] purchaseIds)
    {
        return toAjax(purchasesService.deletePurchasesByPurchaseIds(purchaseIds));
    }
}

        7.0 销售记录管理功能

        对药品进行销售、销毁处理等操作。

相关源码:

@RestController
@RequestMapping("/manage/sales")
public class SalesController extends BaseController
{
    @Autowired
    private ISalesService salesService;

    /**
     * 查询销售记录列表
     */
    @PreAuthorize("@ss.hasPermi('manage:sales:list')")
    @GetMapping("/list")
    public TableDataInfo list(Sales sales)
    {
        startPage();
        List<Sales> list = salesService.selectSalesList(sales);
        return getDataTable(list);
    }

    /**
     * 导出销售记录列表
     */
    @PreAuthorize("@ss.hasPermi('manage:sales:export')")
    @Log(title = "销售记录", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    public void export(HttpServletResponse response, Sales sales)
    {
        List<Sales> list = salesService.selectSalesList(sales);
        ExcelUtil<Sales> util = new ExcelUtil<Sales>(Sales.class);
        util.exportExcel(response, list, "销售记录数据");
    }

    /**
     * 获取销售记录详细信息
     */
    @PreAuthorize("@ss.hasPermi('manage:sales:query')")
    @GetMapping(value = "/{saleId}")
    public AjaxResult getInfo(@PathVariable("saleId") Long saleId)
    {
        return success(salesService.selectSalesBySaleId(saleId));
    }

    /**
     * 新增销售记录
     */
    @PreAuthorize("@ss.hasPermi('manage:sales:add')")
    @Log(title = "销售记录", businessType = BusinessType.INSERT)
    @PostMapping
    public AjaxResult add(@RequestBody Sales sales)
    {
        return toAjax(salesService.insertSales(sales));
    }

    /**
     * 修改销售记录
     */
    @PreAuthorize("@ss.hasPermi('manage:sales:edit')")
    @Log(title = "销售记录", businessType = BusinessType.UPDATE)
    @PutMapping
    public AjaxResult edit(@RequestBody Sales sales)
    {
        return toAjax(salesService.updateSales(sales));
    }

    /**
     * 删除销售记录
     */
    @PreAuthorize("@ss.hasPermi('manage:sales:remove')")
    @Log(title = "销售记录", businessType = BusinessType.DELETE)
	@DeleteMapping("/{saleIds}")
    public AjaxResult remove(@PathVariable Long[] saleIds)
    {
        return toAjax(salesService.deleteSalesBySaleIds(saleIds));
    }
}

        8.0 退货记录管理功能

        药品进行合理的退货,需要对库存进行同步的调整。

相关源码:

@RestController
@RequestMapping("/manage/returns")
public class ReturnsController extends BaseController
{
    @Autowired
    private IReturnsService returnsService;

    /**
     * 查询退货记录列表
     */
    @PreAuthorize("@ss.hasPermi('manage:returns:list')")
    @GetMapping("/list")
    public TableDataInfo list(Returns returns)
    {
        startPage();
        List<Returns> list = returnsService.selectReturnsList(returns);
        return getDataTable(list);
    }

    /**
     * 导出退货记录列表
     */
    @PreAuthorize("@ss.hasPermi('manage:returns:export')")
    @Log(title = "退货记录", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    public void export(HttpServletResponse response, Returns returns)
    {
        List<Returns> list = returnsService.selectReturnsList(returns);
        ExcelUtil<Returns> util = new ExcelUtil<Returns>(Returns.class);
        util.exportExcel(response, list, "退货记录数据");
    }

    /**
     * 获取退货记录详细信息
     */
    @PreAuthorize("@ss.hasPermi('manage:returns:query')")
    @GetMapping(value = "/{returnId}")
    public AjaxResult getInfo(@PathVariable("returnId") Long returnId)
    {
        return success(returnsService.selectReturnsByReturnId(returnId));
    }

    /**
     * 新增退货记录
     */
    @PreAuthorize("@ss.hasPermi('manage:returns:add')")
    @Log(title = "退货记录", businessType = BusinessType.INSERT)
    @PostMapping
    public AjaxResult add(@RequestBody Returns returns)
    {
        return toAjax(returnsService.insertReturns(returns));
    }

    /**
     * 修改退货记录
     */
    @PreAuthorize("@ss.hasPermi('manage:returns:edit')")
    @Log(title = "退货记录", businessType = BusinessType.UPDATE)
    @PutMapping
    public AjaxResult edit(@RequestBody Returns returns)
    {
        return toAjax(returnsService.updateReturns(returns));
    }

    /**
     * 删除退货记录
     */
    @PreAuthorize("@ss.hasPermi('manage:returns:remove')")
    @Log(title = "退货记录", businessType = BusinessType.DELETE)
	@DeleteMapping("/{returnIds}")
    public AjaxResult remove(@PathVariable Long[] returnIds)
    {
        return toAjax(returnsService.deleteReturnsByReturnIds(returnIds));
    }
}

        9.0 库存变动管理功能

        对药品进行采购、销售、调整都会进行记录。

相关源码:

@RestController
@RequestMapping("/manage/movements")
public class InventoryMovementsController extends BaseController
{
    @Autowired
    private IInventoryMovementsService inventoryMovementsService;

    /**
     * 查询库存变动记录列表
     */
    @PreAuthorize("@ss.hasPermi('manage:movements:list')")
    @GetMapping("/list")
    public TableDataInfo list(InventoryMovements inventoryMovements)
    {
        startPage();
        List<InventoryMovements> list = inventoryMovementsService.selectInventoryMovementsList(inventoryMovements);
        return getDataTable(list);
    }

    /**
     * 导出库存变动记录列表
     */
    @PreAuthorize("@ss.hasPermi('manage:movements:export')")
    @Log(title = "库存变动记录", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    public void export(HttpServletResponse response, InventoryMovements inventoryMovements)
    {
        List<InventoryMovements> list = inventoryMovementsService.selectInventoryMovementsList(inventoryMovements);
        ExcelUtil<InventoryMovements> util = new ExcelUtil<InventoryMovements>(InventoryMovements.class);
        util.exportExcel(response, list, "库存变动记录数据");
    }

    /**
     * 获取库存变动记录详细信息
     */
    @PreAuthorize("@ss.hasPermi('manage:movements:query')")
    @GetMapping(value = "/{movementId}")
    public AjaxResult getInfo(@PathVariable("movementId") Long movementId)
    {
        return success(inventoryMovementsService.selectInventoryMovementsByMovementId(movementId));
    }

    /**
     * 新增库存变动记录
     */
    @PreAuthorize("@ss.hasPermi('manage:movements:add')")
    @Log(title = "库存变动记录", businessType = BusinessType.INSERT)
    @PostMapping
    public AjaxResult add(@RequestBody InventoryMovements inventoryMovements)
    {
        return toAjax(inventoryMovementsService.insertInventoryMovements(inventoryMovements));
    }

    /**
     * 修改库存变动记录
     */
    @PreAuthorize("@ss.hasPermi('manage:movements:edit')")
    @Log(title = "库存变动记录", businessType = BusinessType.UPDATE)
    @PutMapping
    public AjaxResult edit(@RequestBody InventoryMovements inventoryMovements)
    {
        return toAjax(inventoryMovementsService.updateInventoryMovements(inventoryMovements));
    }

    /**
     * 删除库存变动记录
     */
    @PreAuthorize("@ss.hasPermi('manage:movements:remove')")
    @Log(title = "库存变动记录", businessType = BusinessType.DELETE)
	@DeleteMapping("/{movementIds}")
    public AjaxResult remove(@PathVariable Long[] movementIds)
    {
        return toAjax(inventoryMovementsService.deleteInventoryMovementsByMovementIds(movementIds));
    }
}

        10.0 SQL 数据库设计

create database pharmaceuticals;

-- 创建供应商表
CREATE TABLE suppliers (
    supplier_id INT AUTO_INCREMENT PRIMARY KEY COMMENT '供应商ID',
    img varchar(100) comment '照片',
    name VARCHAR(100) NOT NULL COMMENT '供应商名称',
    contact_person VARCHAR(100) COMMENT '联系人',
    phone VARCHAR(20) COMMENT '联系电话',
    email VARCHAR(100) COMMENT '电子邮箱',
    address TEXT COMMENT '地址',
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
    updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间'
) COMMENT='供应商信息表';


-- 创建药品表
CREATE TABLE medicines (
    medicine_id INT AUTO_INCREMENT PRIMARY KEY COMMENT '药品ID',
    name VARCHAR(100) NOT NULL COMMENT '药品名称',
    img varchar(100) comment '照片',
    generic_name VARCHAR(100) COMMENT '通用名',
    form tinyint COMMENT '剂型(如固体等)',
    expiration_date DATE COMMENT '有效期至',
    purchase_price DECIMAL(10, 2) COMMENT '进货价',
    sale_price DECIMAL(10, 2) COMMENT '售价',
    stock_quantity INT DEFAULT 0 COMMENT '库存数量',
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
    updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间'
) COMMENT='药品信息表';



-- 创建采购记录表
CREATE TABLE purchases (
    purchase_id INT AUTO_INCREMENT PRIMARY KEY COMMENT '采购ID',
    supplier_id INT NOT NULL COMMENT '供应商ID(逻辑外键关联suppliers表的supplier_id)',
    medicine_id INT NOT NULL COMMENT '药品ID(逻辑外键关联medicines表的medicine_id)',
    quantity INT NOT NULL COMMENT '数量',
    unit_price DECIMAL(10, 2) NOT NULL COMMENT '单价',
    purchase_date DATE NOT NULL COMMENT '采购日期',
    total_amount DECIMAL(10, 2) NOT NULL COMMENT '总金额',
    user_id INT NOT NULL COMMENT '创建人(逻辑外键关联users表的user_id)',
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
    updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间'
) COMMENT='采购记录表';

insert into purchases(supplier_id, medicine_id, quantity, unit_price, purchase_date, total_amount, user_id) values (1,1,10,30,now(),300,1);


-- 创建销售记录表
CREATE TABLE sales (
    sale_id INT AUTO_INCREMENT PRIMARY KEY COMMENT '销售ID',
    sale_date DATE NOT NULL COMMENT '销售日期',
    customer_name VARCHAR(100) COMMENT '客户姓名',
    customer_phone VARCHAR(20) COMMENT '客户电话',
    supplier_id INT NOT NULL COMMENT '供应商ID(逻辑外键关联suppliers表的supplier_id)',
    medicine_id INT NOT NULL COMMENT '药品ID(逻辑外键关联medicines表的medicine_id)',
    quantity INT NOT NULL COMMENT '数量',
    unit_price DECIMAL(10, 2) NOT NULL COMMENT '单价',
    total_amount DECIMAL(10, 2) NOT NULL COMMENT '总金额',
    user_id INT NOT NULL COMMENT '负责人(逻辑外键关联users表的user_id)',
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
    updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间'
) COMMENT='销售记录表';

insert into sales(sale_date, customer_name, customer_phone, supplier_id, medicine_id, quantity, unit_price, total_amount, user_id) VALUES
                  (now(),'小扳手','11789332791',1,1,1,40,40,1);


use pharmaceuticals;

-- 创建退货记录表
CREATE TABLE returns (
    return_id INT AUTO_INCREMENT PRIMARY KEY COMMENT '退货ID',
    customer_name VARCHAR(100) COMMENT '客户姓名',
    customer_phone VARCHAR(20) COMMENT '客户电话',
    medicine_id INT NOT NULL COMMENT '药品ID(逻辑外键关联medicines表的medicine_id)',
    supplier_id INT NOT NULL COMMENT '供应商ID(逻辑外键关联suppliers表的supplier_id)',
    sale_date DATE NOT NULL COMMENT '销售日期',
    sale_id INT NOT NULL COMMENT '销售ID(逻辑外键关联sales表的sale_id)',
    return_date DATE NOT NULL COMMENT '退货日期',
    total_amount DECIMAL(10, 2) NOT NULL COMMENT '退货总金额',
    reason TEXT COMMENT '退货原因',
    user_id INT NOT NULL COMMENT '处理人(逻辑外键关联users表的user_id)',
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
    updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间'
) COMMENT='退货记录表';

-- 创建库存变动记录表
CREATE TABLE inventory_movements (
    movement_id INT AUTO_INCREMENT PRIMARY KEY COMMENT '变动ID',
    supplier_id INT NOT NULL COMMENT '供应商ID(逻辑外键关联suppliers表的supplier_id)',
    medicine_id INT NOT NULL COMMENT '药品ID(逻辑外键关联medicines表的medicine_id)',
    movement_type INT NOT NULL COMMENT '变动类型:1.进货、2.销售、3.调整',
    quantity INT NOT NULL COMMENT '变动数量',
    movement_date DATE NOT NULL COMMENT '变动日期',
    reference_id INT COMMENT '参考ID(例如采购单ID或销售单ID)',
    note TEXT COMMENT '备注',
    user_id INT NOT NULL COMMENT '负责人(逻辑外键关联users表的user_id)',
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
    updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间'
) COMMENT='库存变动记录表';

        若需要项目完整源码,可以在 CSDN 私信给我,我每天都有查看消息的,感谢大家支持,希望可以帮助到大家!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/937945.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

PCIE概述

PCIE概述 文章目录 PCIE概述前言一、应用场景二、PCIE理论2.1 硬件2.2 拓扑结构&#xff1a;处理器和设备之间的关系2.3 速率2.4 层次接口2.5 四种请求类型2.5.1 bar空间2.5.2 memory2.5.3 IO2.5.4 configuration2.5.5 message 前言 参考链接&#xff1a; pcie总线知识点解析 …

基于C#开发web网页管理系统模板流程-登录界面和主界面

点击返回目录-> 基于C#开发web网页管理系统模板流程-总集篇-CSDN博客 前言&#xff0c;首先介绍一下本项目将要实现的功能 &#xff08;一&#xff09;登录界面 实现一个不算特别美观的登录窗口&#xff0c;当然这一步跟开发者本身的设计美学相关&#xff0c;像蒟蒻博主就没…

优化你的 3D Tiles:性能与质量的平衡

优化你的 3D Tiles&#xff1a;性能与质量的平衡 在现代的三维场景渲染中&#xff0c;3D Tiles 是一种强大的技术&#xff0c;它能以高效、分级加载的方式呈现海量的三维数据。然而&#xff0c;优化 3D Tiles 以实现性能与质量的平衡&#xff0c;却是一个复杂且关键的任务。本…

Unix 和 Windows 的有趣比较

Unix 和 Windows NT 比较 来源于这两本书&#xff0c;把两本书对照来读&#xff0c;发现很多有意思的地方&#xff1a; 《Unix 传奇》 https://book.douban.com/subject/35292726/ 《观止 微软创建NT和未来的夺命狂奔 》 Showstopper!: The Breakneck Race to Create Windows…

数据可视化大屏UI组件库:B端科技感素材PSD

在数据可视化领域&#xff0c;一个出色的大屏UI设计不仅能够准确传达数据背后的信息&#xff0c;更能提升用户的视觉体验。然而&#xff0c;对于UI设计师而言&#xff0c;设计这样一款界面往往面临着寻找合适设计素材的挑战。为了应对这一难题&#xff0c;我们推出了这款数据可…

爬虫逆向学习(十四):分享一下某数通用破解服务开发经验

阅前须知 这篇博客不是教大家怎么实现的&#xff0c;而且告知大家有这个东西&#xff0c;或者说一种趋势&#xff0c;借此分享自己大致的实现经验。具体的实现我也不好整理&#xff0c;毕竟是在别人的基础上缝缝补补。 前言 使用补环境方式破解过某数的同学都知道&#xff0…

结合Gitee、PicGo和Typora构建一个免费的个人笔记工具

文章目录 &#x1f4dd;小引言&#x1f4dd;步骤与内容&#x1f4dd;简单使用Typora&#x1f4dd;Gitee和GitHub&#x1f4dd;使用GiteePicGo打造自己的图床Gitee建仓库Node环境配置PicGo软件安装及配置Typora测试 &#x1f4dd;美化Typora &#x1f4dd;小引言 不知道大家在写…

快速本地化部署 OnlyOffice服务 ( Linux+Docker)

文章目录 一、OnlyOffice介绍&#x1f4d6;二、集成OnlyOffice&#x1f9e9;2.1 环境准备&#x1f5a5;️2.2 搜索镜像2.3 拉取镜像2.4 查看镜像2.5 创建容器2.6 进入容器配置2.7 重启服务2.8 添加字体字号2.9 测试OnlyOffice服务 三、在线预览office文档四、Cpolar内网穿透 一…

数字产业化和产业数字化到底是什么?

“数字产业化”和“产业数字化”在很多官方文件和领导人讲话中都是成对出现的&#xff0c;这两个术语看起来非常相似&#xff0c;但它们作为数字经济的两个重要组成部分&#xff0c;既有联系又有区别。 在谈数字产业化和产业数字化之前&#xff0c;我这里需要先给大家介绍一个概…

RabbitMQ中的Work Queues模式

在现代分布式系统中&#xff0c;消息队列&#xff08;Message Queue&#xff09;是实现异步通信和解耦系统的关键组件之一。RabbitMQ 是一个广泛使用的开源消息代理软件&#xff0c;支持多种消息传递模式。其中&#xff0c;Work Queues&#xff08;工作队列&#xff09;模式是一…

数据结构(二叉树)

前言&#xff1a; 在数据结构那片浩瀚无垠、仿若神秘宇宙的天地里&#xff0c;二叉树宛如一颗散发着独特光辉、极为耀眼的星辰。它就像一位技艺精湛的建筑师&#xff0c;运用独特的二叉分支结构&#xff0c;精心构建起层次分明、秩序井然的数据组织 “大厦”。根节点仿若大厦的…

React简单入门 - [Next.js项目] - 页面跳转、AntD组件、二级目录等

须知 1Next.js 官网(英文)Next.js by Vercel - The React Framework2Next.js 文档(中文)简介 | Next.js 中文文档3React官网(中文)https://react.docschina.org/learn4Ant Design组件总览组件总览 - Ant Design5tailwindcss类名大全 官网英Justify Content - TailwindCS…

【MySQL数据库】Ubuntu下的mysql

目录 1&#xff0c;安装mysql数据库 2&#xff0c;mysql默认安装路径 3&#xff0c;my.cnf配置文件 4&#xff0c;mysql运用的相关指令及说明 5&#xff0c;数据库、表的备份和恢复 mysql是一套给我们提供数据存取的&#xff0c;更加有利于管理数据的服务的网络程序。下面…

elasticsearch设置密码访问

1 用户认证介绍 默认ES是没有设置用户认证访问的&#xff0c;所以每次访问时&#xff0c;直接调相关API就能查询和写入数据。现在做一个认证&#xff0c;只有通过认证的用户才能访问和操作ES。 2 开启加密设置 1.生成证书文件 /usr/share/elasticsearch/bin/elasticsearch-…

深入理解 CSS 文本换行: overflow-wrap 和 word-break

前言 正常情况下&#xff0c;在固定宽度的盒子中的中文会自动换行。但是&#xff0c;当遇到非常长的英文单词或者很长的 URL 时&#xff0c;文本可能就不会自动换行&#xff0c;而会溢出所在容器。幸运的是&#xff0c;CSS 为我们提供了一些和文本换行相关的属性&#xff1b;今…

Java 垃圾回收机制详解

1 垃圾回收的概念 垃圾回收&#xff08;Garbage Collection&#xff0c;GC&#xff09;是自动管理内存的一种机制&#xff0c;用于释放不再使用的对象所占用的内存空间&#xff0c;防止内存溢出。垃圾回收器通过识别和回收那些已经死亡或长时间未使用的对象&#xff0c;来优化…

RabbitMQ全局流量控制

RabbitMQ全局流量控制 流控机制流控是对什么进行控制&#xff1f;rabbitmq进程邮箱流控机制是什么&#xff1f; 流控原理流控原理流程 流控状态显示流控对象流控机制对象主要进程各进程状态情形分析 性能提升提升队列性能方式 当消息积压时&#xff0c;消息会进入到队列深处&am…

Jetpack Compose赋能:以速破局,高效打造非凡应用

Android Compose 是谷歌推出的一种现代化 UI 框架&#xff0c;基于 Kotlin 编程语言&#xff0c;旨在简化和加速 Android 应用开发。它以声明式编程为核心&#xff0c;与传统的 View 系统相比&#xff0c;Compose 提供了更直观、更简洁的开发体验。以下是对 Android Compose 的…

40 基于单片机的温湿度检测判断系统

目录 一、主要功能 二、硬件资源 三、程序编程 四、实现现象 一、主要功能 基于STC89C52单片机&#xff0c;采用dht11温湿度传感器检测温湿度&#xff0c; 通过lcd1602显示屏各个参数&#xff0c;四个按键分别可以增加温湿度的阈值&#xff0c; 如果超过阈值&#xff0c;则…