数据库设计——医药销售管理系统

开发环境和开发工具

操作系统:win8.1
开发环境:Mysql、Web
开发工具:Workbench、Eclipse、JDBC

功能需求分析

  • 员工有权查看、添加会员,查看、添加供应商,查询药品(输入药品编号或名称、类别等查询该药品或该类药品库存),添加药品采购记录,销售药品,处理退货,盘点仓库,查看销售、退货、入库记录,修改个人信息
  • 经理有权查看、添加、删除会员,查看、添加、删除供应商,查看、添加、删除员工,盘点仓库,查看销售、退货、入库记录,修改个人信息,无权进行销售和退货业务
  • 供应商和顾客对此系统没有使用权限 系统设计

这里写图片描述

系统设计

  • 数据流
    这里写图片描述
  • E-R图
    这里写图片描述
  • 数据库关系模式设计

    登录用户(用户编号,用户名,密码,类别)
    员工(员工编号,员工姓名,联系电话,用户编号)
    经理(经理编号,用户编号)
    财政收支(收支编号,药品编号,员工编号,数量,日期,总额,类型)
    供应商(供应商编号,供应商名称,联系人,联系方式,所在城市)
    会员(客户编号,客户姓名,联系方式)
    入库记录(入库记录编号,供应商编号,收支编号)
    退货管理(退货编号,销售编号,收支编号)
    销售管理(销售编号,客户编号,收支编号)
    药品(药品编号,药品名称,供应商编号,生产批号,产地,所属类别,进价,单价,会员折扣,库存,包装规格,生产日期,有效期)

  • 数据库物理结构设计

    本次项目使用的引擎是InnoDB,MySQL的数据库引擎之一。InnoDB存储引擎为在主内存中缓存数据和索引而维持它自己的缓冲池。InnoDB存储它的表&索引在一个表空间中,表空间可以包含数个文件(或原始磁盘分区)。这与MyISAM表不同,比如在MyISAM表中每个表被存在分离的文件中。InnoDB 表可以是任何尺寸,即使在文件尺寸被限制为2GB的操作系统上。InnoDB默认地被包含在MySQL二进制分发中。Windows Essentials installer使InnoDB成为Windows上MySQL的默认表。

    此外还使用了数据库索引,索引是对数据库表中一列或多列的值进行排序的一种结构,使用索引可快速访问数据库表中的特定信息。各表索引如下:
    会员:primary key(客户编号)
    药品:primary key(药品编号),
    INDEX 供应商编号_idx (供应商编号 ASC),
    供应商:primary key(供应商编号)
    登录用户:primary key(用户编号)
    用户名 unique,
    经理:primary key(经理编号),
    INDEX 经理编号_idx (用户编号 ASC),
    员工:primary key(员工编号),
    INDEX 员工编号_idx (用户编号 ASC),
    财政收支:PRIMARY KEY (收支编号),
    INDEX 药品编号_idx (药品编号 ASC),
    INDEX 员工编号_idx (员工编号 ASC),
    入库记录:primary key(入库记录编号),
    INDEX 供应商编号_idx (供应商编号 ASC),
    INDEX 收支编号_idx (收支编号 ASC),
    销售管理:PRIMARY KEY (销售编号),
    INDEX 客户编号_idx (客户编号 ASC),
    INDEX 收支编号_idx (收支编号 ASC),
    退货管理:PRIMARY KEY (退货编号),
    INDEX 销售编号_idx (销售编号 ASC),
    INDEX 收支编号_idx (收支编号 ASC),

系统功能的实现

  • 建表

    drop database if exists 医药销售管理系统;
    create database 医药销售管理系统;
    use 医药销售管理系统;
    //建立表 会员
    create table `会员`(
        客户编号      int auto_increment,
        客户姓名      varchar(50),
        联系方式      varchar(100),
    primary key(客户编号));
    //建立表 供应商
    create table `供应商`(
        供应商编号     int auto_increment,
        供应商名称     varchar(50),
        联系人         varchar(50),
        联系方式       varchar(50),
        所在城市       varchar(50),
    primary key(供应商编号));
    //建立表 药品
    create table `药品`(
        药品编号    int auto_increment,
        药品名称    varchar(50) not null,
        供应商编号  int not null,
        生产批号    varchar(100),
        产地        varchar(50),
        所属类别    varchar(50),
        进价        decimal(10,2) not null,
        单价        decimal(10,2) not null,
        会员折扣    decimal(3,2),
        库存        int not null,
        包装规格    varchar(50),
        生产日期    varchar(50),
        有效期      varchar(50),
    primary key(药品编号),
    INDEX `供应商编号_idx` (`供应商编号` ASC),
    CONSTRAINT `供应商编号`
    FOREIGN KEY (`供应商编号`)
    REFERENCES `医药销售管理系统`.`供应商` (`供应商编号`)
    ON DELETE CASCADE
    ON UPDATE CASCADE);
    //建立表登录用户,可以登录医药销售管理系统,类别为1代表员工,2代表经理
    create table `登录用户`(
        用户编号         int auto_increment,
        用户名          varchar(40) not null unique,
        密码           varchar(40) not null,
        类别             int not null,
    primary key(用户编号));
    //建立表经理,具有登录用户编号,可登录系统
    create table `经理`(
        经理编号      int auto_increment,
        用户编号      int not null,
    primary key(经理编号),
    INDEX `经理编号_idx` (`用户编号` ASC),
    CONSTRAINT `经理登陆编号`
    FOREIGN KEY (`用户编号`)
    REFERENCES `医药销售管理系统`.`登录用户` (`用户编号`)
    ON DELETE CASCADE
    ON UPDATE CASCADE);
    //建立表员工,具有登录用户编号,可登录系统
    create table `员工`(
        员工编号      int auto_increment,
        员工姓名      varchar(50),
        联系电话      varchar(100),
        用户编号      int not null,
    primary key(员工编号),
    INDEX `员工编号_idx` (`用户编号` ASC),
    CONSTRAINT `员工登陆编号`
    FOREIGN KEY (`用户编号`)
    REFERENCES `医药销售管理系统`.`登录用户` (`用户编号`)
    ON DELETE CASCADE
    ON UPDATE CASCADE);
    //建立表财政开支,涉及药品编号、负责员工、数量、金额等信息,类型有入库、销售、退货等
    CREATE TABLE `财政收支` (
    `收支编号` int auto_increment,
    `药品编号` int,
    `员工编号` int not null,
    `数量` int,
    `日期` datetime NOT NULL,
    `总额` decimal(10,2) NOT NULL,
    `类型` VARCHAR(20)  NOT NULL,
    PRIMARY KEY (`收支编号`),
    INDEX `药品编号_idx` (`药品编号` ASC),
    CONSTRAINT `药品编号`
    FOREIGN KEY (`药品编号`)
    REFERENCES `医药销售管理系统`.`药品` (`药品编号`)
    ON DELETE CASCADE
    ON UPDATE CASCADE,
    INDEX `员工编号_idx` (`员工编号` ASC),
    CONSTRAINT `负责员工编号`
    FOREIGN KEY (`员工编号`)
    REFERENCES `医药销售管理系统`.`员工` (`员工编号`)
    ON DELETE CASCADE
    ON UPDATE CASCADE);
    //建立表入库记录,包含供应商、收支编号
    create table `入库记录`(
        入库记录编号   int auto_increment,
        供应商编号     int not null,
        收支编号       int not null,
    primary key(入库记录编号),
    INDEX `供应商编号_idx` (`供应商编号` ASC),
    INDEX `收支编号_idx` (`收支编号` ASC),
    CONSTRAINT `入货供应商编号`
    FOREIGN KEY (`供应商编号`)
    REFERENCES `医药销售管理系统`.`供应商` (`供应商编号`)
    ON DELETE CASCADE
    ON UPDATE CASCADE,
    CONSTRAINT `入库收支编号`
    FOREIGN KEY (`收支编号`)
    REFERENCES `医药销售管理系统`.`财政收支` (`收支编号`)
    ON DELETE CASCADE
    ON UPDATE CASCADE);
    //建立表销售管理,包含客户、收支编号
    CREATE TABLE `销售管理`(
    `销售编号` int auto_increment,
    `客户编号` int,
    `收支编号` int not null,
    PRIMARY KEY (`销售编号`),
    INDEX `客户编号_idx` (`客户编号` ASC),
    INDEX `收支编号_idx` (`收支编号` ASC),
    CONSTRAINT `销售客户编号`
    FOREIGN KEY (`客户编号`)
    REFERENCES `医药销售管理系统`.`会员` (`客户编号`)
    ON DELETE CASCADE
    ON UPDATE CASCADE,
    CONSTRAINT `销售收支编号`
    FOREIGN KEY (`收支编号`)
    REFERENCES `医药销售管理系统`.`财政收支` (`收支编号`)
    ON DELETE CASCADE
    ON UPDATE CASCADE);
    //建立表退货管理,包含销售、收支编号
    CREATE TABLE `退货管理` (
    `退货编号` int auto_increment,
    `销售编号` int NOT NULL,
    `收支编号` int NOT NULL,
    PRIMARY KEY (`退货编号`),
    INDEX `销售编号_idx` (`销售编号` ASC),
    INDEX `收支编号_idx` (`收支编号` ASC),
    CONSTRAINT `退货销售编号`
    FOREIGN KEY (`销售编号`)
    REFERENCES `医药销售管理系统`.`销售管理` (`销售编号`)
    ON DELETE CASCADE
    ON UPDATE CASCADE,
    CONSTRAINT `退货收支编号`
    FOREIGN KEY (`收支编号`)
    REFERENCES `医药销售管理系统`.`财政收支` (`收支编号`)
    ON DELETE CASCADE
    ON UPDATE CASCADE);
  • 创建视图方便查询

    
    /*仓库*/
    drop view if exists warehouse; 
    create view warehouse as
    select 药品编号,药品名称,供应商名称,生产批号,产地,所属类别,进价,单价,会员折扣,库存,包装规格,生产日期,有效期
    from 药品,供应商 where 药品.供应商编号=供应商.供应商编号; 
    /*入库记录*/
    drop view if exists InDrug_records; 
    create view InDrug_records as
    select 入库记录编号,药品名称,供应商名称,员工姓名,数量,日期,总额 
    from 入库记录,供应商,财政收支,员工,药品
    where 入库记录.供应商编号=供应商.供应商编号 and 入库记录.收支编号=财政收支.收支编号 and
    财政收支.员工编号=员工.员工编号 and 财政收支.药品编号=药品.药品编号;
    /*销售记录*/
    drop view if exists sales_records; 
    create view sales_records as
    select 销售编号,药品.药品编号,药品名称,单价,会员折扣,库存,客户姓名,员工姓名,数量,日期,总额
    from 销售管理,会员,财政收支,员工,药品
    where 销售管理.客户编号=会员.客户编号 and 销售管理.收支编号=财政收支.收支编号
    and 财政收支.员工编号=员工.员工编号 and 财政收支.药品编号=药品.药品编号;
    /*退货记录*/
    drop view if exists reject_records;
    create view reject_records as
    select 退货编号,退货管理.销售编号,药品名称,客户姓名,员工姓名,数量,日期,总额
    from 退货管理,销售管理,会员,财政收支,员工,药品
    where 退货管理.销售编号=销售管理.销售编号 and 销售管理.客户编号=会员.客户编号 
    and 退货管理.收支编号=财政收支.收支编号 and 财政收支.员工编号=员工.员工编号 
    and 财政收支.药品编号=药品.药品编号;
    /*员工信息*/
    drop view if exists employee_info;
    create view employee_info as
    select 员工编号,员工姓名,联系电话,员工.用户编号,用户名 from `员工` natural join `登录用户`;
    /*收支记录*/
    drop view if exists financial_records;
    create view financial_records as
    select 类型,药品名称,数量,日期,总额 
    from `财政收支` left join `药品` on `财政收支`.药品编号=`药品`.`药品编号`;
  • 使用过程实现“带参数的视图“

    drop procedure if exists payments_statistics;
    delimiter //
    create procedure payments_statistics(in date_limit varchar(20))
    begin
        select count(*) as 数目,sum(`总额`) as 盈亏, 
        (select sum(`总额`) from `财政收支` where `总额` < 0 and `日期` like date_limit) as '支出', 
        (select sum(`总额`) from `财政收支` where `总额` >= 0 and `日期` like date_limit) as '收入' 
        from `财政收支` where `日期` like date_limit;
    end//

    JDBC调用方法如下

                //调用过程  -- 统计盈亏、收入、支出
                CallableStatement cStmt = con.prepareCall("{call payments_statistics(?)}");
                cStmt.setString(1,"%"+date+"%");
                cStmt.execute();
                rs = cStmt.getResultSet();
                if(rs.next()){
                    count = rs.getInt(1);
                    all = rs.getString(2);
                    allOut = rs.getString(3);
                    allIn = rs.getString(4);
                }
                rs.close();
  • 建立触发器保证逻辑正确

    
    drop trigger if exists stock_update;
    delimiter //
    create trigger stock_update before update on 药品
    for each row
    begin
        if new.库存 < 0
        /* MySQL不支持直接使用rollback回滚事务,可以利用delete当前表造成异常使事务回滚 */
        then delete from 药品 where 药品编号=new.药品编号;  
        end if;
    end //
    update 药品 set 库存=-2 where 药品编号=1;
    
    drop trigger if exists drugs_insert;
    delimiter //
    create trigger drugs_insert before insert on 药品
    for each row
    begin
        if new.库存 < 0 or new.单价 < 0 or new.进价 < 0 or new.会员折扣 > 1 or new.会员折扣 < 0
        then delete from 药品 where 药品编号=new.药品编号;
        end if;
    end //
    /*退货数量不应比售出的多*/
    drop trigger if exists refunds_insert;
    delimiter //
    create trigger refunds_insert after insert on 退货管理
    for each row
    begin
        if (select 数量 from sales_records where 销售编号 = new.销售编号) < (select 数量 from reject_records where 退货编号 = new.退货编号)
        then delete from 退货管理 where 退货编号=new.退货编号;
        end if;
    end //
  • 将业务逻辑封装为事务,如销售事务

    PreparedStatement ps=null;
    Connection con = DriverManager.getConnection(connectString,"root", "2333");
    ...
            con.setAutoCommit(false);//设置自动提交为false
            ...
            //销售事务 
            //更新库存
            String fmt1="update 药品  set `库存`='%d' where `药品编号`='%s'";
            String sql1 = String.format(fmt1,drug_rest-pcount,drug_id); 
            ps = con.prepareStatement(sql1);
            ps.executeUpdate();
            //插入财政收支记录
            String fmt2="INSERT INTO `财政收支` (`药品编号`,`员工编号`,`数量`,`日期`,`总额`,`类型`) VALUES ('%s','%d','%d','%s','%s','销售')";
            String sql2 = String.format(fmt2,drug_id,employee_id,pcount,today,money); 
            ps = con.prepareStatement(sql2);
            ps.executeUpdate(); 
            //获取插入的财政收支编号
            ps = con.prepareStatement("select @@identity;");
            rs = ps.executeQuery();
            if(rs.next()){
                financial_id=rs.getInt(1);
            }
            rs.close();
            //插入销售记录
            String fmt3="insert into 销售管理(客户编号,收支编号) values(%s,'%d')";
            String sql3 = String.format(fmt3,customer_id,financial_id); 
            ps = con.prepareStatement(sql3);
            ps.executeUpdate();
            //提交事务
            con.commit();
      }catch(Exception e){
         try {
             con.rollback();
         } catch (Exception e1) {
             e1.printStackTrace();
         }

界面效果

登陆
这里写图片描述
主页
这里写图片描述
仓库
这里写图片描述
点击新增进行药品入库
这里写图片描述
入库/销售/退货记录
这里写图片描述
员工可查看/增加客户,供应商
这里写图片描述
经理可增删员工、客户、供应商
这里写图片描述
销售药品
这里写图片描述
这里写图片描述
退货
这里写图片描述
财务统计
这里写图片描述

(项目见https://github.com/14353350/Drug_Sales_Management

  • 71
    点赞
  • 708
    收藏
    觉得还不错? 一键收藏
  • 19
    评论
酒店管理系统是一个常见的数据库课程设计项目,它涉及到数据库设计、数据模型、触发器、前后端连接等多个方面。以下是一个简单的介绍: 1. 数据库设计:酒店管理系统数据库设计是整个项目的基础。它包括定义表、字段、主键、外键等。可以使用E-R图来表示实体和关系,以及流程图和模块图来表示系统的功能和模块。 2. 触发器:触发器是数据库中的一种特殊对象,它可以在特定的数据库操作(如插入、更新、删除)发生时自动执行一些操作。在酒店管理系统中,可以使用触发器来实现一些业务逻辑,例如在预订房间时自动更新房间的状态。 3. Python编程:在酒店管理系统中,可以使用Python编程语言来实现一些功能,例如与数据库的交互、数据处理、界面设计等。同时,还可以使用一些第三方库来简化开发过程,例如Django、Flask等。 4. 前后端连接:酒店管理系统通常包括一个前端界面和一个后端数据库。前端界面用于用户交互和数据展示,后端数据库用于存储和管理数据。可以使用Python的Web框架(如Django)来实现前后端的连接,通过HTTP请求和数据库交互来实现数据的增删改查。 总结起来,酒店管理系统是一个综合性的数据库课程设计项目,涉及到数据库设计、触发器、Python编程和前后端连接等多个方面。通过这个项目,你可以学到数据库设计的基本原理和方法,以及如何使用Python来实现一个完整的应用系统。
评论 19
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值