项目介绍 基于Python的客房预订系统设计和实现(含模型描述及部分示例代码)
基于Python的客房预订系统设计和实现的详细项目实例
请注意此篇内容只是一个项目介绍 更多详细内容可直接联系博主本人
或者访问对应标题的完整博客或者文档下载页面(含完整的程序,GUI设计和代码详解)
基于Python的客房预订系统,源于当下酒店与民宿行业在数字化过程中面临的一系列现实需求。传统的客房预订方式长期依赖前台人工登记、电话预约以及纸质台账管理,不仅费时费力,而且极易出现信息遗漏、超卖房间、入住信息记录不完整等问题。随着线上旅游平台的普及,越来越多的酒店希望通过信息系统实现客房库存、订单和客户信息的一体化管理,而并非仅仅依托第三方平台。这种诉求不仅来自大型连锁酒店,也大量存在于中小型宾馆、家庭旅馆和城市公寓式酒店中。
基于Python的客房预订系统从设计之初就定位为一个能够兼顾易开发、易维护、扩展性强的管理系统原型。一方面,Python语言本身拥有简洁的语法和丰富的标准库,在数据处理、文件持久化、日期时间计算等方面具有明显优势;另一方面,大量成熟的第三方库(如SQLite数据库驱动、ORM工具、Web框架等)能够显著缩短开发周期、降低开发难度,使得客房预订系统可以从简单的命令行版本逐步演进到图形界面版甚至Web版。
现实业务中的客房预订涉及多个核心维度:房型管理、价格管理、预订时间管理、入住和退房管理、客户信息管理以及报表统计等。这些功能在纸质或Excel表格中虽然可以勉强实现,但无法很好地满足多终端同时操作、快速查询、历史记录追踪、权限控制及数据安全等需求。基于Python的客房预订系统,通过模块化设计,将房间、订单、客户、支付和报表逻辑分别封装,使得每一个部分既可以独立测试,又能通过清晰的数据模型进行组合和扩展。
从信息化建设的角度看,一个扎实的客房预订系统原型不仅有助于企业内部业务流程梳理,也能为后续接入微信公众号、小程序、第三方支付、门锁系统以及会员积分体系打下基础。通过系统化管理客房预订流程,可以显著降低人工错误率,提高房间利用率,提升客户入住体验。例如,系统可以自动检测预订日期是否与现有订单冲突、自动计算房费、自动生成入住登记记录,并在达到退房日期时提醒前台确认离店状态,从而实现更精细化的运营管理。
在教学与学习场景中,基于Python的客房预订系统也是非常典型且完整的课程设计或项目实战题材。其业务逻辑清晰,不仅涵盖基本的增删改查操作,还牵涉到时间区间冲突检测、状态机设计(预订、已入住、已退房、取消等不同状态)、数据持久化与异常处理等内容。通过完整实现这一项目,可以全面锻炼开发者在需求分析、系统设计、编码实现、测试调试以及后期优化方面的综合能力,为进一步学习大型Web系统、分布式系统打下实践基础。
在当前数字经济背景下,中小住宿业对轻量级、可定制的客房预订系统需求持续存在。采用Python设计和实现一个可扩展的系统原型,一方面能够快速落地基础功能,另一方面也能作为脚手架被持续迭代和二次开发。随着业务发展,可以在原有架构上逐步加入角色权限管理、在线支付接口、短信提醒、数据可视化报表等高级特性,使得客房预订系统从简单工具成长为支撑经营决策的重要平台。这种从基础到高级的演进路线,正是基于Python的客房预订系统设计与实现项目的现实背景与价值所在。
项目目标与意义
提升客房管理效率与准确性
客房预订管理的首要目标在于提升日常运营效率,并最大限度减少人工操作带来的错误。在传统模式下,前台人员需要通过本子、表格或者简单软件记录每一位客户的入住和退房信息,一旦遇到旺季、团体入住或者连续多日的长住客,手工核对预订时间和房间余量就会变得极为繁琐。基于Python的客房预订系统,将房间信息、预订记录、入住状态集中存储在统一的数据模型中,通过程序自动校验时间区间冲突,避免同一房间在同一时间段被重复出售。系统可在创建订单时自动检测某房间在指定起止日期是否已有订单记录,如果存在重叠则立即拒绝并提示选择其他房间。
在效率方面,系统能够通过一条命令或一个按钮完成通常需要多次人工填写的操作,例如:创建预订时自动生成订单编号、计算总房费、记录客户联系方式、标记预订来源等。入住时,只需将订单状态从“已预订”更新为“已入住”,系统就会自动记录入住时间,并可同步更新房态统计。退房时,系统可以快速计算住宿天数和最终费用,即便涉及延住、提前退房等特殊情况,也能通过算法自动给出正确结果。这种高度自动化和规则化的处理,不仅使前台操作更加轻松,也大幅提高数据记录的完整性与一致性,为后续统计分析提供可靠依据。
优化客户体验与服务质量
从客户角度来看,顺畅的预订体验远不止“有房间就可以入住”那么简单。现代住客更希望在预订阶段就清晰看到房型信息、价格、可入住时间和退房规则,同时在入住前后能够享受透明、便捷的服务流程。基于Python构建的客房预订系统,通过模块化设计,可以很容易地扩展前端接口形式,例如命令行操作初版完成后,可进一步封装为Web接口或者轻量桌面程序,让客户或者前台人员能够快速查询房态并完成预订操作。在预订确认环节,系统可自动生成清晰的订单信息,包括入住日期、退房日期、房型、价格明细等,避免因为口头沟通不清造成误解。
在入住和退房环节,利用系统记录的完整订单信息,可以缩短办理时间,减少重复询问和信息填写,让客户感受到更加专业高效的服务。系统还可以记录客户历史入住记录,在后续再次预订时快速检索,以便提供个性化服务,如优先安排偏好楼层、偏好床型等。此外,系统中的数据积累还能支持运营方分析客户来源、入住频率、平均停留时间等指标,从而优化营销策略和服务套餐设计。长远来看,这种基于数据驱动的客户体验优化,将形成良性循环,使客房预订系统从一个“登记工具”升级为提升服务质量的重要基础设施。
为数字化转型和数据分析提供基础
对于酒店、民宿等住宿业者来说,客房预订系统不仅是日常运营工具,也是在数字化转型过程中积累业务数据的关键入口。通过Python实现的系统可以方便地与数据分析工具结合,例如借助pandas进行数据清洗与统计,借助Matplotlib或其他可视化库生成报表,从入住率、RevPAR(每可供出租客房收入)、平均房价等指标角度评估运营表现。只有在预订系统层面保证数据记录的完整性和标准化,后续的数据分析和决策才有可靠基础。
在数字化转型目标下,该系统的意义还体现在与其他系统的对接潜力上。借助Python强大的网络和API处理能力,可以逐步将本地客房预订系统与线上渠道管理系统、财务系统、会员系统等打通,实现数据自动同步,减少重复录入。同时,系统产生的历史数据能够用于训练简单的预测模型,例如基于季节、节假日、历史入住情况预测未来某段时间的需求量,为调价、促销策略提供参考。尽管初期系统规模可能较小,但通过规范的数据结构,每一次预订都在为未来更智能的运营打基础。这种从“可用”向“可分析”“可决策”的演进,是项目在企业数字化进程中的重要意义。
作为Python综合实战项目的教学与实践价值
从教学和个人成长角度看,基于Python的客房预订系统是一个非常适合用来训练综合开发能力的项目。项目涵盖需求分析、面向对象设计、数据库建模、业务流程抽象、错误处理、日志记录以及代码重构等多个层面,有助于开发者从零到一地完成一个“能跑起来”的系统。在实现过程中,需要设计Room(房间)、Booking(预订)、Customer(客户)等实体类,思考它们之间的关系和交互方式,这本身就是面向对象分析与设计的良好训练。
同时,项目实现中还要处理真实业务中的复杂情况,例如同一客户多次预订、跨月甚至跨年的入住时间、预订取消与退款、超时未入住处理等,这些都要求在代码中对时间处理和状态流转给予足够重视。通过反复调试系统,可以进一步理解异常处理、测试用例设计以及代码结构优化的重要性。此外,在完成基础版系统后,还可以选择性地引入图形界面库、Web框架、ORM框架,甚至Docker部署等技术,将项目逐步扩展为更完整的软件系统。整个过程兼具实用性和实践性,使项目成为学习Python开发道路上的重要里程碑。
项目挑战及解决方案
复杂时间区间与房态冲突管理的挑战与应对
客房预订系统中最核心也是最具挑战性的问题之一,是如何正确处理预订时间区间与房态冲突。每一个房间在任意时间段内只能被一位客户占用,但实际业务中预订情况复杂多样:有的客户只住一晚,有的住数日,有的跨周跨月,还有临时延住、提前退房等情况。处理不当就会产生超卖、重复预订或空置浪费等问题。编写系统时,不能仅仅用简单的“起始日期不同”来判断是否冲突,而要判断时间区间是否重叠,例如新订单的入住日期小于已有订单的退房日期,同时新订单的退房日期大于已有订单的入住日期,就意味着发生冲突。
为解决这一挑战,系统在设计阶段需要引入统一的日期时间表示方式,将所有日期转换为Python的date或datetime对象,避免字符串比较导致的错误。在对每个新建预订进行验证时,针对同一房间,查询其所有已存在的预订记录,并逐条检测时间区间是否重叠。为了保证性能和可靠性,可在数据模型中为房间预订表添加索引,按照房间编号和日期区间进行筛选,减少无关记录遍历。在业务逻辑层面,则将“可预订性检查”封装为独立函数,避免重复代码,并确保逻辑集中易于维护。一旦检测到冲突,系统要给出明确提示,如“该房间在所选日期已有预订,请更换日期或房间”,并避免创建错误订单。
此外,延住和提前退房也是时间处理中的难点。延住操作本质上是修改原订单的退房日期,需要再次对延住后的新时间区间进行冲突验证,避免“抢占”了后续客户预订的时间。提前退房则涉及到费用重算和状态更新,系统要谨慎处理“入住天数”和“计费天数”的差异,确保财务数据准确。通过构建完善的时间处理工具函数,将日期差计算、区间重叠判断等逻辑封装起来,可以极大降低业务代码复杂度,使系统在面对多种复杂场景时仍能保持行为稳定。
数据持久化、一致性与异常情况处理的挑战与应对
客房预订系统需要长期稳定运行,且要保证客户信息、订单记录、房态信息不会因为程序异常或机器故障而轻易丢失,这对数据持久化和一致性提出了要求。很多简单示例程序可能只把数据保存在内存中或一次性写入文本文件,这在演示阶段勉强可用,但无法满足实际场景中对可靠性的需求。合适的解决方案是选择轻量级数据库如SQLite,通过Python标准库或第三方ORM组件进行读写,既无需复杂部署,又具备事务机制和查询能力。
在设计数据库结构时,需要为房间、客户、预订订单等实体分别建立数据表,并通过外键或字段关联它们的关系。例如,预订表中需要包含房间id、客户id、入住日期、退房日期、状态等字段。系统业务逻辑中的每一次写操作,最好被封装在事务中,当某个操作中途失败时可以回滚,避免只保存了部分数据,造成信息不一致。此外,在处理高频操作如连续预订时,要考虑并发场景下可能出现的“脏读”或“并发修改”问题,即两个操作几乎同时检查房态并创建订单。虽然单机版本难以模拟高强度并发,但在设计结构时仍可预留扩展空间,例如对关键查询加锁或使用数据库约束,保证同一房间同一日期不出现重复记录。
异常情况处理也是数据一致性的重要组成部分。系统运行过程中可能遇到各种异常,例如用户输入格式错误、日期无效、数据库连接失败、磁盘空间不足等。业务代码在处理用户请求时,需要对关键步骤添加异常捕获和友好提示,避免程序直接崩溃,同时保证数据不会处于“不确定状态”。例如,在创建新预订时,如果写入数据库途中出现异常,程序应回滚事务并通知调用者操作失败,而不是保存一半的信息。通过设计细致的异常处理分支和日志记录机制,可以在错误发生时快速定位原因,修复问题并恢复系统正常运行,为长期稳定运营打下坚实基础。
系统扩展性、模块化设计与后续升级的挑战与应对
许多软件项目在初版实现时往往只关注“能用”,而忽略了扩展性和可维护性,导致后续功能增加变得困难、代码难以阅读甚至不得不推倒重来。客房预订系统的业务本身具有天然扩展性:初始版本只需要完成基本预订和入住管理,但随着业务发展,很可能需要增加会员管理、价格体系(平日价、周末价、节假日价)、多房型管理、分店管理、在线支付、短信通知等模块。如果一开始代码组织混乱,各种业务逻辑写在一起,没有清晰的分层和模块划分,那么每扩展一项功能都会带来巨大维护成本,也容易引入新bug。
为解决这一挑战,系统设计时需要贯彻“分层与模块化”的思想。可以将系统划分为数据访问层、业务逻辑层和界面层三个主要部分。数据访问层专注于数据库操作,提供增删改查接口,不掺杂业务规则;业务逻辑层负责处理预订、取消、入住、退房等业务流程,调用数据访问层完成数据存取;界面层(命令行或Web等)则负责接收用户输入、展示处理结果,不直接操作数据库。这种分层结构使得在更换存储方案(例如从SQLite迁移到MySQL)或更换界面形式(从命令行迁移到Web)时,只需要修改相应层的实现,而无需大幅冲击其他部分。
模块化设计方面,可以按业务实体划分模块,如room模块处理房间相关逻辑,booking模块处理预订逻辑,customer模块处理客户信息管理,report模块生成统计报表。每个模块内部再细分类与函数,并避免过多跨模块互相依赖。通过为关键类与函数编写单元测试,可以在升级和重构时迅速验证核心逻辑是否仍然正确。为便于后续扩展,还可以在设计数据模型时预留若干字段,例如在订单表中增加“渠道来源”“促销活动编号”等可空字段,以便以后扩展营销相关功能而不必大幅修改结构。通过前瞻性的架构设计,客房预订系统能够在满足当前需求的同时,为未来功能迭代留出充足空间,让整个项目具备“越用越好用”的生命力。
项目模型架构
整体分层架构设计
客房预订系统在整体架构上采用清晰的三层结构:表示层、业务逻辑层与数据访问层。表示层负责与操作人员或前端程序交互,可以是命令行界面、图形界面或者Web接口;业务逻辑层承载预订、入住、退房、取消、查询等核心流程;数据访问层则负责与底层数据库交互,实现实体对象与持久化数据之间的映射和同步。这样的分层设计可以显著提升系统的可维护性与可扩展性,使不同层之间通过定义良好的接口进行通信,而不会产生混乱的依赖关系。
表示层中,最初版本可以使用简单的文本菜单或函数调用形式,用以驱动业务逻辑层的各项功能。随着系统演进,可以将这些调用封装在Web框架的路由函数中,实现HTTP接口,而底层业务代码基本不需要改变。业务逻辑层是系统的核心,由多个服务类或管理类组成,如RoomService、BookingService、CustomerService等,每个服务负责一个相对独立的领域,内部实现细节对外部隐藏。数据访问层则通过Repository模式或简单的数据访问对象,将操作数据库的细节封装起来,对业务层提供简洁的接口。例如,booking_repository.create(booking)负责在数据库中新增一条预订记录,而业务层只需准备好Booking对象并调用该方法即可。
这种架构的优势在于:当需要切换数据库技术(从SQLite到PostgreSQL)或添加缓存机制(如在内存中缓存高频查询结果)时,只需改动数据访问层即可;当需要新增预订规则(如最短入住天数、预付金额校验)时,只需扩展业务逻辑层而不影响存储实现;当需要增加一个新的前端形式(例如移动端小程序)时,则主要集中在表示层的开发。通过严格控制各层的职责边界,项目可以在功能不断扩展的同时保持代码结构清晰,降低维护成本,便于团队协作和长期迭代。
核心实体模型设计
在客房预订系统中,实体模型是整个架构的基础。主要实体包括Room(房间)、RoomType(房型)、Customer(客户)、Booking(预订订单)以及PaymentRecord(支付记录)等。Room实体通常包含房间编号、房型、楼层、当前状态(空房、已预订、已入住、维修中等);RoomType实体包含房型名称、基础价格、最多入住人数、描述等;Customer实体包含姓名、联系方式、证件信息、备注等;Booking实体则关联房间和客户,记录入住日期、退房日期、订单状态(待入住、已入住、已退房、已取消等)、总价、创建时间等;PaymentRecord用于记录支付金额、支付时间、支付方式、关联的预订订单等信息。
在实体之间的关联关系上,RoomType与Room是一对多关系,一个房型对应多个具体房间;Customer与Booking也是一对多关系,一个客户可以拥有多个预订记录;Booking与Room通常是一对一关系(每条预订对应一个具体房间),在扩展到“按房型预订、到店分配房间”的模式时,可能演变为先预订RoomType再分配Room。通过为这些实体定义清晰的数据结构和对象表示,可以在业务逻辑层中更自然地表达各种操作,如“查询某客户最近三次入住记录”或“统计某房型本月的入住率”。
在具体实现中,可以采用面向对象方式,为每个实体定义对应的Python类,并包含必要的属性和方法。例如,Booking类中除了基本字段外,还可以提供计算入住天数、计算总价、判断当前状态是否合法流转等方法。通过将业务相关的行为封装到实体类中,可以避免大量散落在各处的重复逻辑,使代码更具内聚性与可读性。实体模型一旦设计合理,就会成为系统演进过程中的稳定基石,为后续的逻辑扩展和性能优化提供坚实基础。
数据库与持久化层架构
数据持久化层是确保客房预订系统数据可靠保存和高效查询的关键部分。项目采用SQLite作为基础数据库,这种嵌入式关系型数据库无需单独服务器,使用文件进行存储,非常适合中小规模应用与教学实践。在持久化层中,为每个实体定义对应的数据表:rooms表存储房间信息,room_types表存储房型信息,customers表存储客户信息,bookings表存储预订订单,payments表存储支付记录。通过外键字段建立实体之间的关联,例如bookings表中的room_id指向rooms表的主键,customer_id指向customers表的主键。
在数据访问层实现上,可以直接使用Python的sqlite3模块进行SQL操作,也可以引入轻量级ORM(对象关系映射)工具,如SQLAlchemy,使得在业务逻辑层能使用面向对象方式操作数据,而不需要直接书写SQL。无论采用哪种方式,数据访问层都应提供清晰的接口,例如create_booking、get_bookings_by_room_and_date_range、update_booking_status等函数或方法。通过这种接口封装,业务逻辑层只需要关注领域操作而无需关心底层SQL语句与连接管理。
为了保证数据一致性和性能,数据库架构中还需要考虑索引设计与约束。对高频查询的字段,如room_id、check_in_date、check_out_date等,适当创建索引可以显著提升查询效率。通过添加唯一约束,可以防止某些逻辑错误,比如禁止同一预订编号重复插入。在事务管理方面,数据访问层在执行一系列相关数据库操作时,应使用事务机制保证要么全部成功、要么全部回滚,避免部分更新成功导致数据状态不一致。例如,在创建预订订单时,如果需要同时写入bookings表和payments表,就必须保证两者同时成功或同时撤销。通过精心设计数据库与持久化层架构,系统可以在可靠性与性能之间达到良好平衡。
业务逻辑与服务层架构
业务逻辑与服务层是整个客房预订系统的“中枢神经”,负责实现从界面输入到数据存储之间的完整业务路径。该层将复杂业务拆分成一系列清晰的服务或管理器,例如RoomService负责房间相关操作,BookingService负责预订和入住管理,CustomerService负责客户信息管理,PaymentService负责支付处理等。每个服务内部调用数据访问层的接口完成数据操作,同时实现具体业务规则,例如预订冲突检查、状态流转校验、金额计算规则等。
在架构设计上,业务逻辑层应尽量保持无状态或者弱状态特性,即不依赖于全局可变变量,而是基于参数和数据库数据计算结果。这种设计可以让业务代码更容易测试和重用,也为未来的并发扩展和分布式部署提供可能。预订流程可以被抽象为若干步骤:验证输入(日期格式、房间存在性、客户信息完整性)、检查房态(通过数据访问层查询重叠预订)、计算费用(根据房型价格和入住天数)、创建订单(插入数据库记录)、返回结果(订单编号和状态)。每个步骤可以实现为独立函数或方法,在主流程中按顺序调用,使逻辑结构清晰可循。
在状态机设计方面,Booking实体的状态流转需要在业务逻辑层得到严格控制。例如,初始状态为“已预订”,在实际入住时变更为“已入住”,在退房后变更为“已退房”,在超时未入住或主动取消时变更为“已取消”。业务层需要定义一套允许的状态转换表,禁止非法转换,例如不允许从“已退房”再次变更为“已入住”。同时,还要考虑某些操作所带来的连锁反应,例如取消预订后要释放相应时间段的房态占用标记,退房后要触发统计模块更新入住率等。通过完善的业务逻辑与服务层架构,系统可以在处理复杂流程时保持逻辑严谨与扩展灵活。
扩展模块与接口架构设计
除了基础的预订、入住和退房管理,客房预订系统在架构层面还需要考虑未来扩展模块与外部接口的接入。扩展模块包括统计报表模块、会员积分模块、优惠券与活动模块、渠道管理模块等。这些功能通常围绕已有实体展开,如在Booking和Customer数据基础上统计各种运营指标或计算积分。在架构设计时,可以为扩展模块预留独立的名字空间或子包,如reports、loyalty、promotion等,使新功能的开发与部署不会打乱现有代码结构。
外部接口架构是系统走向开放和协同的重要方向。基于Python的系统可以利用Web框架(例如FastAPI、Flask等)提供REST风格的API,对外暴露客房查询、创建订单、取消订单等接口。接口层接收HTTP请求后,调用业务逻辑层完成操作,并将结果以JSON等格式返回前端或其他系统。同时,在需要与第三方支付平台、短信网关、门锁系统等对接时,也应通过清晰的接口适配层进行隔离。例如,定义一个统一的PaymentGateway接口,内部再根据配置选择支付宝、微信支付或其他渠道的具体实现,而业务层只需调用统一接口即可。
在安全性和权限控制方面,接口架构也要有所布局。对于管理端接口,需要进行认证与授权,限制只有拥有相应角色的用户才能执行敏感操作,如退款、价格调整等。虽然在初始版本中可以只实现简单的鉴权方式,但在设计上可以通过中间件或装饰器预留扩展点,为后续引入JWT、OAuth等较完善机制打基础。通过面向扩展的接口与模块架构,客房预订系统能够在不牺牲稳定性的前提下不断融入新的功能与外部系统,逐步成长为一个功能完整、开放互联的业务平台。
项目模型描述及代码示例
房间与房型基础模型示例
class RoomType: # 定义房型类,用于描述客房的类型及价格等基础信息
def init(self, type_id: int, name: str, base_price: float, capacity: int, description: str = ""): # 构造函数,初始化房型编号、名称、基础价格、可入住人数和描述
self.type_id = type_id # 保存房型编号,用于在数据库或列表中唯一标识某个房型
self.name = name # 保存房型名称,例如“大床房”“双床房”“家庭房”等,便于界面展示
self.base_price = base_price # 保存房型的基础价格,作为计算房费的起点,可在业务中叠加其它规则
self.capacity = capacity # 保存该房型允许的最大入住人数,用于预订时限制人数
self.description = description # 保存房型的文字描述,如房间面积、是否含早餐等,用于展示给客户
def __repr__(self) -> str: # 定义对象的字符串表达形式,便于调试和日志记录
class Room: # 定义房间类,用于描述单个具体房间的属性和状态
def init(self, room_id: int, room_number: str, room_type: RoomType, floor: int, status: str = "空房"): # 构造函数,初始化房间编号、房号、房型、楼层和状态
self.room_id = room_id # 保存房间编号,用作数据库主键或内存索引
self.room_number = room_number # 保存用于展示和查找的房号,例如“801”或“A302”等
self.room_type = room_type # 保存与该房间关联的房型对象,用于查询价格和容量等信息
self.floor = floor # 保存房间所在楼层,方便前台安排和客户偏好选择
self.status = status # 保存当前房态,如“空房”“已预订”“已入住”“维修中”等
self.status = "已预订" # 将状态字段更新为“已预订”,用于前台和系统逻辑识别
def mark_occupied(self) -> None: # 定义将房间标记为已入住的函数
self.status = "已入住" # 将状态字段更新为“已入住”,表明当前房间有客人入住
self.status = "空房" # 将状态字段更新为空房,表示可以被新订单使用
def __repr__(self) -> str: # 定义房间对象的字符串表达形式,便于打印和调试
return f"Room(id={self.room_id}, no={self.room_number}, type={self.room_type.name}, status={self.status})" # 返回包含房间编号、房号、房型名称和状态的文本
客户与预订实体模型示例
from datetime import date # 导入日期类,用于表示入住和退房的具体日期
class Customer: # 定义客户类,用于保存客户的个人信息和联系信息
def init(self, customer_id: int, name: str, phone: str, id_number: str = "", note: str = ""): # 构造函数,初始化客户编号、姓名、电话、证件号和备注
self.customer_id = customer_id # 保存客户编号,用于与预订、入住记录关联
self.name = name # 保存客户姓名,用于显示和入住登记
self.phone = phone # 保存客户手机号,便于联系和发送提醒消息
self.id_number = id_number # 保存客户证件号码,如身份证或护照等,满足入住登记要求
self.note = note # 保存备注信息,如客户特殊偏好或重要说明
def __repr__(self) -> str: # 定义客户对象的字符串表示形式
class Booking: # 定义预订类,用于描述一次完整的客房预订及其状态
def init(self, booking_id: int, room: Room, customer: Customer, check_in: date, check_out: date, status: str = "已预订", created_at: date | None = None): # 构造函数,初始化预订编号、房间、客户、入住退房日期、状态和创建时间
self.booking_id = booking_id # 保存预订编号,用来在系统中唯一标识该订单
self.room = room # 保存关联的房间对象,用以记录该预订对应哪一个房间
self.customer = customer # 保存关联的客户对象,用以记录预订人和入住人信息
self.check_in = check_in # 保存预计入住日期,用于房态冲突检查和费用计算
self.check_out = check_out # 保存预计退房日期,用于房态占用区间计算
self.status = status # 保存预订状态,如“已预订”“已入住”“已退房”“已取消”等
self.created_at = created_at or date.today() # 保存预订创建日期,默认为当前日期,用于统计分析等
def stay_nights(self) -> int: # 定义计算入住晚数的函数
return (self.check_out - self.check_in).days # 使用日期差计算入住天数,用退房日期减入住日期得到天数
nights = self.stay_nights() # 调用内部函数获取入住晚数
return nights * self.room.room_type.base_price # 使用入住晚数乘以房型基础价格得到总房费
def can_check_in(self) -> bool: # 定义判断订单是否可办理入住的函数
def mark_checked_in(self) -> None: # 定义将预订标记为已入住的函数
if self.can_check_in(): # 检查当前状态是否允许入住
self.room.mark_occupied() # 同时将关联房间标记为已入住,保持房态一致
else: # 当状态不允许入住时执行的逻辑分支
def can_check_out(self) -> bool: # 定义判断订单是否可办理退房的函数
return self.status == "已入住" # 只有状态为“已入住”的订单才允许办理退房
def mark_checked_out(self) -> None: # 定义将预订标记为已退房的函数
if self.can_check_out(): # 检查当前状态是否允许退房
self.status = "已退房" # 更新订单状态为已退房
def cancel(self) -> None: # 定义取消预订的函数
self.room.mark_free() # 释放房间,使房态恢复为空房
else: # 当订单已经入住或退房后不允许取消
def __repr__(self) -> str: # 定义预订对象的字符串表示形式
return f"Booking(id={self.booking_id}, room={self.room.room_number}, customer={self.customer.name}, status={self.status})" # 返回包含订单编号、房号、客户姓名和状态的简要描述
from datetime import date # 导入日期类型,用于参与区间运算
def is_room_available_for_period(room: Room, existing_bookings: list[Booking], new_start: date, new_end: date) -> bool: # 定义函数判断某房间在指定时间段是否有空
for booking in existing_bookings: # 遍历该房间的所有已有预订记录
if booking.room.room_id != room.room_id: # 若当前订单对应的是其他房间,则跳过本次循环
continue # 继续下一条订单检查
if booking.status in ("已取消",): # 若订单已取消,则不再占用房态
continue # 继续检查下一条订单
if is_overlap(booking.check_in, booking.check_out, new_start, new_end): # 调用区间重叠函数检查时间是否冲突
return False # 一旦发现重叠则直接返回不可用,表示房间在该时间段已被占用
return True # 若遍历结束未发现任何冲突,则返回可用,表示可以创建新预订
数据持久化与SQLite数据库操作示例
@contextmanager # 使用装饰器将函数包装为上下文管理器,便于使用with语句确保资源释放
def get_connection(db_path: str): # 定义函数获取数据库连接对象,参数为数据库文件路径
conn = sqlite3.connect(db_path) # 通过sqlite3.connect建立到指定数据库文件的连接
try: # 使用try块包裹需要安全执行的代码
yield conn # 将连接对象交给调用方使用,在with语句中作为上下文变量出现
conn.commit() # 若with代码块正常结束,则提交事务,将所有修改写入磁盘
except Exception as e: # 捕获在with代码块中可能抛出的异常
conn.rollback() # 回滚事务,撤销本次操作中的所有更新,避免数据处于不一致状态
raise e # 重新抛出异常,交给上层处理或记录日志
finally: # 无论是否发生异常都执行finally部分
conn.close() # 关闭数据库连接,释放系统资源
def init_db(db_path: str) -> None: # 定义函数初始化数据库结构,在第一次运行时创建数据表
with get_connection(db_path) as conn: # 使用自定义的上下文管理器安全打开数据库连接
cur = conn.cursor() # 获取游标对象,用于执行SQL语句
cur.execute( # 执行创建rooms表的SQL语句,用于保存房间信息
"CREATE TABLE IF NOT EXISTS rooms (" # 创建表头,IF NOT EXISTS保证表不存在时才创建
"id INTEGER PRIMARY KEY AUTOINCREMENT," # 定义自增主键字段id,用于唯一标识每个房间
"room_number TEXT NOT NULL," # 定义room_number字段,用于保存房号,不能为空
"room_type TEXT NOT NULL," # 定义room_type字段,用于保存房型名称或编号
"floor INTEGER NOT NULL," # 定义floor字段,用于保存楼层信息
"status TEXT NOT NULL" # 定义status字段,用于保存房态,如空房、已预订等
")" # 结束CREATE TABLE语句
) # 结束execute调用
cur.execute( # 执行创建bookings表的SQL语句,用于保存预订订单
"CREATE TABLE IF NOT EXISTS bookings (" # 创建表头,保证表不存在时才执行创建
"id INTEGER PRIMARY KEY AUTOINCREMENT," # 定义自增主键字段id,用于唯一标识每个预订
"room_id INTEGER NOT NULL," # 定义room_id字段,用于关联rooms表的主键
"customer_name TEXT NOT NULL," # 定义customer_name字段,用于保存预订人姓名
"customer_phone TEXT NOT NULL," # 定义customer_phone字段,用于保存预订人电话
"check_in DATE NOT NULL," # 定义check_in字段,用于保存入住日期
"check_out DATE NOT NULL," # 定义check_out字段,用于保存退房日期
"status TEXT NOT NULL," # 定义status字段,用于保存订单状态
"FOREIGN KEY(room_id) REFERENCES rooms(id)" # 定义外键约束,保证room_id对应rooms表的记录
")" # 结束CREATE TABLE语句
) # 结束execute调用
def insert_booking(db_path: str, room_id: int, customer_name: str, customer_phone: str, check_in: date, check_out: date, status: str = "已预订") -> None: # 定义向bookings表插入预订记录的函数
with get_connection(db_path) as conn: # 打开数据库连接并自动管理提交或回滚
cur = conn.cursor() # 获取游标对象
cur.execute( # 执行插入SQL语句
"INSERT INTO bookings (room_id, customer_name, customer_phone, check_in, check_out, status) VALUES (?, ?, ?, ?, ?, ?)", # 定义插入字段和占位符
(room_id, customer_name, customer_phone, check_in.isoformat(), check_out.isoformat(), status), # 将日期类型转换为字符串并作为参数传入
) # 结束execute调用
def load_room(self, room_id: int) -> Room | None: # 定义加载单个房间信息的函数
with get_connection(self.db_path) as conn: # 通过上下文管理器打开数据库连接
cur.execute("SELECT id, room_number, room_type, floor, status FROM rooms WHERE id = ?", (room_id,)) # 执行查询SQL,从rooms表按id获取房间信息
return None # 返回空值,让调用方决定如何处理
room_type = RoomType(0, row[2], 0.0, 2, "") # 简单构造房型对象,此处仅填充房型名称与默认值,可在扩展阶段替换为真正房型表
def load_bookings_for_room(self, room_id: int) -> list[Booking]: # 定义加载某房间所有预订记录的函数
bookings: list[Booking] = [] # 初始化空列表,用于存放查询结果对应的Booking对象
with get_connection(self.db_path) as conn: # 打开数据库连接
cur = conn.cursor() # 获取游标对象
(room_id,), # 提供参数元组,绑定room_id
dummy_customer = Customer(0, "占位客户", "00000000000") # 构造一个占位客户对象,方便在不细分客户表时创建Booking实例
room = self.load_room(room_id) # 调用内部函数加载房间对象
if room is None: # 若房间不存在,则直接返回空列表
return bookings # 返回空预订列表
for row in rows: # 遍历每条查询到的记录
check_in = date.fromisoformat(row[3]) # 将字符串格式的入住日期解析为date对象
check_out = date.fromisoformat(row[4]) # 将字符串格式的退房日期解析为date对象
booking = Booking(booking_id=row[0], room=room, customer=dummy_customer, check_in=check_in, check_out=check_out, status=row[5]) # 根据每行数据构造Booking对象
bookings.append(booking) # 将构造好的Booking对象追加到列表中
return bookings # 返回该房间的所有预订对象列表
def create_booking(self, room_id: int, customer_name: str, customer_phone: str, check_in: date, check_out: date) -> Booking | None: # 定义业务函数实现预订流程
existing_bookings = self.load_bookings_for_room(room_id) # 加载该房间所有既有预订记录
if not is_room_available_for_period(room, existing_bookings, check_in, check_out): # 调用时间区间函数检查是否出现冲突
return None # 返回空值,表示未创建订单
bookings_after = self.load_bookings_for_room(room_id) # 再次查询该房间所有预订,以获取新订单的id等信息
这一部分展示了业务服务层如何将数据库操作与实体模型结合,完整地实现预订流程。通过load_room和load_bookings_for_room函数,从数据库中读取原始记录并转换为Room与Booking对象,再利用is_room_available_for_period执行冲突检测。成功后使用insert_booking写入数据,实现了从请求到持久化的闭环。create_booking函数在结构上清晰地分离了验证与持久化步骤,便于后续添加更多规则(例如最少入住天数)。
def print_daily_report(db_path: str, target_date: date) -> None: # 定义函数打印指定日期的运营日报
status_summary = get_room_status_summary(db_path) # 调用函数获取当前房态统计
occupancy_rate = calculate_occupancy_rate(db_path, target_date) # 调用函数计算指定日期的入住率
print(f"报告日期: {target_date.isoformat()}") # 打印报表日期,采用ISO格式展示
print("房态概况:") # 打印房态概况标题
for status, count in status_summary.items(): # 遍历房态统计字典中的每个状态及其数量
print(f"{status}: {count} 间") # 打印每种状态对应的房间数量,单位为间
print(f"当日入住率: {occupancy_rate * 100:.2f}%") # 将入住率转换为百分比并保留两位小数打印
这一部分展示了如何基于数据库数据生成房态统计和运营报表。get_room_status_summary通过GROUP BY统计各状态房间数,calculate_occupancy_rate通过count distinct room_id计算某日占用房间数量,结合总房数得出入住率。print_daily_report则把统计结果以简单明了的方式输出,可作为命令行报表,也可以在未来改写为Web页面输出。
简易命令行交互驱动示例
def main_menu() -> None: # 定义主菜单函数,用于在命令行中引导操作流程
db_path = "hotel.db" # 指定数据库文件路径,作为整个系统的存储基础
init_db(db_path) # 调用初始化函数,确保数据库结构已经创建
service = BookingService(db_path) # 创建预订服务对象,绑定数据库路径
while True: # 使用无限循环持续展示菜单,直到用户选择退出
print("客房预订系统主菜单") # 打印菜单标题
print("1. 新增房间") # 菜单选项1:新增房间
print("2. 创建预订") # 菜单选项2:创建预订订单
print("3. 查看指定日期运营报表") # 菜单选项3:生成运营报表
print("0. 退出") # 菜单选项0:退出程序
choice = input("请输入操作编号: ").strip() # 获取用户输入的选项并去除首尾空白字符
if choice == "1": # 判断是否选择新增房间
room_number = input("请输入房号: ").strip() # 提示输入房号并读取
room_type = input("请输入房型名称: ").strip() # 提示输入房型名称并读取
floor = int(input("请输入楼层: ").strip()) # 提示输入楼层并转换为整数
insert_room(db_path, room_number, room_type, floor) # 调用insert_room函数向数据库写入房间信息
print("房间添加成功") # 提示用户操作成功
elif choice == "2": # 判断是否选择创建预订
room_id = int(input("请输入房间ID: ").strip()) # 提示输入房间id并转换为整数
customer_name = input("请输入客户姓名: ").strip() # 提示输入客户姓名并读取
customer_phone = input("请输入客户电话: ").strip() # 提示输入客户电话并读取
check_in_str = input("请输入入住日期(YYYY-MM-DD): ").strip() # 提示输入入住日期字符串
check_out_str = input("请输入退房日期(YYYY-MM-DD): ").strip() # 提示输入退房日期字符串
check_in = date.fromisoformat(check_in_str) # 将入住日期字符串转换为date对象
check_out = date.fromisoformat(check_out_str) # 将退房日期字符串转换为date对象
service.create_booking(room_id, customer_name, customer_phone, check_in, check_out) # 调用预订服务创建订单
elif choice == "3": # 判断是否选择查看运营报表
target_str = input("请输入报表日期(YYYY-MM-DD): ").strip() # 提示输入报表日期字符串
target_date = date.fromisoformat(target_str) # 将报表日期字符串转换为date对象
print_daily_report(db_path, target_date) # 调用报表函数打印指定日期运营情况
elif choice == "0": # 判断是否选择退出程序
print("正在退出系统") # 提示退出信息
break # 跳出循环,结束菜单函数
else: # 当输入不在定义的选项中时
print("无效的选项,请重新输入") # 提示用户输入无效并要求重新选择
if name == "main": # 检测当前模块是否作为主程序运行
main_menu() # 调用主菜单函数启动命令行交互
这一部分给出了一个简单但完整的命令行驱动示例,用于操作房间添加、预订创建和报表查看。虽然界面朴素,但结构清晰,能够帮助快速验证前面模型与服务层逻辑是否正确工作。未来可以将main_menu逻辑替换为图形界面或Web路由,而无需修改底层业务与数据库操作函数。
房间与房型基础模型示例
class RoomType: # 定义房型类,用于描述客房的类型及价格等基础信息
def init(self, type_id: int, name: str, base_price: float, capacity: int, description: str = ""): # 构造函数,初始化房型编号、名称、基础价格、可入住人数和描述
self.type_id = type_id # 保存房型编号,用于在数据库或列表中唯一标识某个房型
self.name = name # 保存房型名称,例如“大床房”“双床房”“家庭房”等,便于界面展示
self.base_price = base_price # 保存房型的基础价格,作为计算房费的起点,可在业务中叠加其它规则
self.capacity = capacity # 保存该房型允许的最大入住人数,用于预订时限制人数
self.description = description # 保存房型的文字描述,如房间面积、是否含早餐等,用于展示给客户
def __repr__(self) -> str: # 定义对象的字符串表达形式,便于调试和日志记录
class Room: # 定义房间类,用于描述单个具体房间的属性和状态
def init(self, room_id: int, room_number: str, room_type: RoomType, floor: int, status: str = "空房"): # 构造函数,初始化房间编号、房号、房型、楼层和状态
self.room_id = room_id # 保存房间编号,用作数据库主键或内存索引
self.room_number = room_number # 保存用于展示和查找的房号,例如“801”或“A302”等
self.room_type = room_type # 保存与该房间关联的房型对象,用于查询价格和容量等信息
self.floor = floor # 保存房间所在楼层,方便前台安排和客户偏好选择
self.status = status # 保存当前房态,如“空房”“已预订”“已入住”“维修中”等
self.status = "已预订" # 将状态字段更新为“已预订”,用于前台和系统逻辑识别
def mark_occupied(self) -> None: # 定义将房间标记为已入住的函数
self.status = "已入住" # 将状态字段更新为“已入住”,表明当前房间有客人入住
self.status = "空房" # 将状态字段更新为空房,表示可以被新订单使用
def __repr__(self) -> str: # 定义房间对象的字符串表达形式,便于打印和调试
return f"Room(id={self.room_id}, no={self.room_number}, type={self.room_type.name}, status={self.status})" # 返回包含房间编号、房号、房型名称和状态的文本
客户与预订实体模型示例
from datetime import date # 导入日期类,用于表示入住和退房的具体日期
class Customer: # 定义客户类,用于保存客户的个人信息和联系信息
def init(self, customer_id: int, name: str, phone: str, id_number: str = "", note: str = ""): # 构造函数,初始化客户编号、姓名、电话、证件号和备注
self.customer_id = customer_id # 保存客户编号,用于与预订、入住记录关联
self.name = name # 保存客户姓名,用于显示和入住登记
self.phone = phone # 保存客户手机号,便于联系和发送提醒消息
self.id_number = id_number # 保存客户证件号码,如身份证或护照等,满足入住登记要求
self.note = note # 保存备注信息,如客户特殊偏好或重要说明
def __repr__(self) -> str: # 定义客户对象的字符串表示形式
class Booking: # 定义预订类,用于描述一次完整的客房预订及其状态
def init(self, booking_id: int, room: Room, customer: Customer, check_in: date, check_out: date, status: str = "已预订", created_at: date | None = None): # 构造函数,初始化预订编号、房间、客户、入住退房日期、状态和创建时间
self.booking_id = booking_id # 保存预订编号,用来在系统中唯一标识该订单
self.room = room # 保存关联的房间对象,用以记录该预订对应哪一个房间
self.customer = customer # 保存关联的客户对象,用以记录预订人和入住人信息
self.check_in = check_in # 保存预计入住日期,用于房态冲突检查和费用计算
self.check_out = check_out # 保存预计退房日期,用于房态占用区间计算
self.status = status # 保存预订状态,如“已预订”“已入住”“已退房”“已取消”等
self.created_at = created_at or date.today() # 保存预订创建日期,默认为当前日期,用于统计分析等
def stay_nights(self) -> int: # 定义计算入住晚数的函数
return (self.check_out - self.check_in).days # 使用日期差计算入住天数,用退房日期减入住日期得到天数
nights = self.stay_nights() # 调用内部函数获取入住晚数
return nights * self.room.room_type.base_price # 使用入住晚数乘以房型基础价格得到总房费
def can_check_in(self) -> bool: # 定义判断订单是否可办理入住的函数
def mark_checked_in(self) -> None: # 定义将预订标记为已入住的函数
if self.can_check_in(): # 检查当前状态是否允许入住
self.room.mark_occupied() # 同时将关联房间标记为已入住,保持房态一致
else: # 当状态不允许入住时执行的逻辑分支
def can_check_out(self) -> bool: # 定义判断订单是否可办理退房的函数
return self.status == "已入住" # 只有状态为“已入住”的订单才允许办理退房
def mark_checked_out(self) -> None: # 定义将预订标记为已退房的函数
if self.can_check_out(): # 检查当前状态是否允许退房
self.status = "已退房" # 更新订单状态为已退房
def cancel(self) -> None: # 定义取消预订的函数
self.room.mark_free() # 释放房间,使房态恢复为空房
else: # 当订单已经入住或退房后不允许取消
def __repr__(self) -> str: # 定义预订对象的字符串表示形式
return f"Booking(id={self.booking_id}, room={self.room.room_number}, customer={self.customer.name}, status={self.status})" # 返回包含订单编号、房号、客户姓名和状态的简要描述
from datetime import date # 导入日期类型,用于参与区间运算
def is_room_available_for_period(room: Room, existing_bookings: list[Booking], new_start: date, new_end: date) -> bool: # 定义函数判断某房间在指定时间段是否有空
for booking in existing_bookings: # 遍历该房间的所有已有预订记录
if booking.room.room_id != room.room_id: # 若当前订单对应的是其他房间,则跳过本次循环
continue # 继续下一条订单检查
if booking.status in ("已取消",): # 若订单已取消,则不再占用房态
continue # 继续检查下一条订单
if is_overlap(booking.check_in, booking.check_out, new_start, new_end): # 调用区间重叠函数检查时间是否冲突
return False # 一旦发现重叠则直接返回不可用,表示房间在该时间段已被占用
return True # 若遍历结束未发现任何冲突,则返回可用,表示可以创建新预订
数据持久化与SQLite数据库操作示例
@contextmanager # 使用装饰器将函数包装为上下文管理器,便于使用with语句确保资源释放
def get_connection(db_path: str): # 定义函数获取数据库连接对象,参数为数据库文件路径
conn = sqlite3.connect(db_path) # 通过sqlite3.connect建立到指定数据库文件的连接
try: # 使用try块包裹需要安全执行的代码
yield conn # 将连接对象交给调用方使用,在with语句中作为上下文变量出现
conn.commit() # 若with代码块正常结束,则提交事务,将所有修改写入磁盘
except Exception as e: # 捕获在with代码块中可能抛出的异常
conn.rollback() # 回滚事务,撤销本次操作中的所有更新,避免数据处于不一致状态
raise e # 重新抛出异常,交给上层处理或记录日志
finally: # 无论是否发生异常都执行finally部分
conn.close() # 关闭数据库连接,释放系统资源
def init_db(db_path: str) -> None: # 定义函数初始化数据库结构,在第一次运行时创建数据表
with get_connection(db_path) as conn: # 使用自定义的上下文管理器安全打开数据库连接
cur = conn.cursor() # 获取游标对象,用于执行SQL语句
cur.execute( # 执行创建rooms表的SQL语句,用于保存房间信息
"CREATE TABLE IF NOT EXISTS rooms (" # 创建表头,IF NOT EXISTS保证表不存在时才创建
"id INTEGER PRIMARY KEY AUTOINCREMENT," # 定义自增主键字段id,用于唯一标识每个房间
"room_number TEXT NOT NULL," # 定义room_number字段,用于保存房号,不能为空
"room_type TEXT NOT NULL," # 定义room_type字段,用于保存房型名称或编号
"floor INTEGER NOT NULL," # 定义floor字段,用于保存楼层信息
"status TEXT NOT NULL" # 定义status字段,用于保存房态,如空房、已预订等
")" # 结束CREATE TABLE语句
) # 结束execute调用
cur.execute( # 执行创建bookings表的SQL语句,用于保存预订订单
"CREATE TABLE IF NOT EXISTS bookings (" # 创建表头,保证表不存在时才执行创建
"id INTEGER PRIMARY KEY AUTOINCREMENT," # 定义自增主键字段id,用于唯一标识每个预订
"room_id INTEGER NOT NULL," # 定义room_id字段,用于关联rooms表的主键
"customer_name TEXT NOT NULL," # 定义customer_name字段,用于保存预订人姓名
"customer_phone TEXT NOT NULL," # 定义customer_phone字段,用于保存预订人电话
"check_in DATE NOT NULL," # 定义check_in字段,用于保存入住日期
"check_out DATE NOT NULL," # 定义check_out字段,用于保存退房日期
"status TEXT NOT NULL," # 定义status字段,用于保存订单状态
"FOREIGN KEY(room_id) REFERENCES rooms(id)" # 定义外键约束,保证room_id对应rooms表的记录
")" # 结束CREATE TABLE语句
) # 结束execute调用
def insert_booking(db_path: str, room_id: int, customer_name: str, customer_phone: str, check_in: date, check_out: date, status: str = "已预订") -> None: # 定义向bookings表插入预订记录的函数
with get_connection(db_path) as conn: # 打开数据库连接并自动管理提交或回滚
cur = conn.cursor() # 获取游标对象
cur.execute( # 执行插入SQL语句
"INSERT INTO bookings (room_id, customer_name, customer_phone, check_in, check_out, status) VALUES (?, ?, ?, ?, ?, ?)", # 定义插入字段和占位符
(room_id, customer_name, customer_phone, check_in.isoformat(), check_out.isoformat(), status), # 将日期类型转换为字符串并作为参数传入
) # 结束execute调用
def load_room(self, room_id: int) -> Room | None: # 定义加载单个房间信息的函数
with get_connection(self.db_path) as conn: # 通过上下文管理器打开数据库连接
cur.execute("SELECT id, room_number, room_type, floor, status FROM rooms WHERE id = ?", (room_id,)) # 执行查询SQL,从rooms表按id获取房间信息
return None # 返回空值,让调用方决定如何处理
room_type = RoomType(0, row[2], 0.0, 2, "") # 简单构造房型对象,此处仅填充房型名称与默认值,可在扩展阶段替换为真正房型表
def load_bookings_for_room(self, room_id: int) -> list[Booking]: # 定义加载某房间所有预订记录的函数
bookings: list[Booking] = [] # 初始化空列表,用于存放查询结果对应的Booking对象
with get_connection(self.db_path) as conn: # 打开数据库连接
cur = conn.cursor() # 获取游标对象
(room_id,), # 提供参数元组,绑定room_id
dummy_customer = Customer(0, "占位客户", "00000000000") # 构造一个占位客户对象,方便在不细分客户表时创建Booking实例
room = self.load_room(room_id) # 调用内部函数加载房间对象
if room is None: # 若房间不存在,则直接返回空列表
return bookings # 返回空预订列表
for row in rows: # 遍历每条查询到的记录
check_in = date.fromisoformat(row[3]) # 将字符串格式的入住日期解析为date对象
check_out = date.fromisoformat(row[4]) # 将字符串格式的退房日期解析为date对象
booking = Booking(booking_id=row[0], room=room, customer=dummy_customer, check_in=check_in, check_out=check_out, status=row[5]) # 根据每行数据构造Booking对象
bookings.append(booking) # 将构造好的Booking对象追加到列表中
return bookings # 返回该房间的所有预订对象列表
def create_booking(self, room_id: int, customer_name: str, customer_phone: str, check_in: date, check_out: date) -> Booking | None: # 定义业务函数实现预订流程
existing_bookings = self.load_bookings_for_room(room_id) # 加载该房间所有既有预订记录
if not is_room_available_for_period(room, existing_bookings, check_in, check_out): # 调用时间区间函数检查是否出现冲突
return None # 返回空值,表示未创建订单
bookings_after = self.load_bookings_for_room(room_id) # 再次查询该房间所有预订,以获取新订单的id等信息
这一部分展示了业务服务层如何将数据库操作与实体模型结合,完整地实现预订流程。通过load_room和load_bookings_for_room函数,从数据库中读取原始记录并转换为Room与Booking对象,再利用is_room_available_for_period执行冲突检测。成功后使用insert_booking写入数据,实现了从请求到持久化的闭环。create_booking函数在结构上清晰地分离了验证与持久化步骤,便于后续添加更多规则(例如最少入住天数)。
def print_daily_report(db_path: str, target_date: date) -> None: # 定义函数打印指定日期的运营日报
status_summary = get_room_status_summary(db_path) # 调用函数获取当前房态统计
occupancy_rate = calculate_occupancy_rate(db_path, target_date) # 调用函数计算指定日期的入住率
print(f"报告日期: {target_date.isoformat()}") # 打印报表日期,采用ISO格式展示
print("房态概况:") # 打印房态概况标题
for status, count in status_summary.items(): # 遍历房态统计字典中的每个状态及其数量
print(f"{status}: {count} 间") # 打印每种状态对应的房间数量,单位为间
print(f"当日入住率: {occupancy_rate * 100:.2f}%") # 将入住率转换为百分比并保留两位小数打印
这一部分展示了如何基于数据库数据生成房态统计和运营报表。get_room_status_summary通过GROUP BY统计各状态房间数,calculate_occupancy_rate通过count distinct room_id计算某日占用房间数量,结合总房数得出入住率。print_daily_report则把统计结果以简单明了的方式输出,可作为命令行报表,也可以在未来改写为Web页面输出。
简易命令行交互驱动示例
def main_menu() -> None: # 定义主菜单函数,用于在命令行中引导操作流程
db_path = "hotel.db" # 指定数据库文件路径,作为整个系统的存储基础
init_db(db_path) # 调用初始化函数,确保数据库结构已经创建
service = BookingService(db_path) # 创建预订服务对象,绑定数据库路径
while True: # 使用无限循环持续展示菜单,直到用户选择退出
print("客房预订系统主菜单") # 打印菜单标题
print("1. 新增房间") # 菜单选项1:新增房间
print("2. 创建预订") # 菜单选项2:创建预订订单
print("3. 查看指定日期运营报表") # 菜单选项3:生成运营报表
print("0. 退出") # 菜单选项0:退出程序
choice = input("请输入操作编号: ").strip() # 获取用户输入的选项并去除首尾空白字符
if choice == "1": # 判断是否选择新增房间
room_number = input("请输入房号: ").strip() # 提示输入房号并读取
room_type = input("请输入房型名称: ").strip() # 提示输入房型名称并读取
floor = int(input("请输入楼层: ").strip()) # 提示输入楼层并转换为整数
insert_room(db_path, room_number, room_type, floor) # 调用insert_room函数向数据库写入房间信息
print("房间添加成功") # 提示用户操作成功
elif choice == "2": # 判断是否选择创建预订
room_id = int(input("请输入房间ID: ").strip()) # 提示输入房间id并转换为整数
customer_name = input("请输入客户姓名: ").strip() # 提示输入客户姓名并读取
customer_phone = input("请输入客户电话: ").strip() # 提示输入客户电话并读取
check_in_str = input("请输入入住日期(YYYY-MM-DD): ").strip() # 提示输入入住日期字符串
check_out_str = input("请输入退房日期(YYYY-MM-DD): ").strip() # 提示输入退房日期字符串
check_in = date.fromisoformat(check_in_str) # 将入住日期字符串转换为date对象
check_out = date.fromisoformat(check_out_str) # 将退房日期字符串转换为date对象
service.create_booking(room_id, customer_name, customer_phone, check_in, check_out) # 调用预订服务创建订单
elif choice == "3": # 判断是否选择查看运营报表
target_str = input("请输入报表日期(YYYY-MM-DD): ").strip() # 提示输入报表日期字符串
target_date = date.fromisoformat(target_str) # 将报表日期字符串转换为date对象
print_daily_report(db_path, target_date) # 调用报表函数打印指定日期运营情况
elif choice == "0": # 判断是否选择退出程序
print("正在退出系统") # 提示退出信息
break # 跳出循环,结束菜单函数
else: # 当输入不在定义的选项中时
print("无效的选项,请重新输入") # 提示用户输入无效并要求重新选择
if name == "main": # 检测当前模块是否作为主程序运行
main_menu() # 调用主菜单函数启动命令行交互
这一部分给出了一个简单但完整的命令行驱动示例,用于操作房间添加、预订创建和报表查看。虽然界面朴素,但结构清晰,能够帮助快速验证前面模型与服务层逻辑是否正确工作。未来可以将main_menu逻辑替换为图形界面或Web路由,而无需修改底层业务与数据库操作函数。




更多详细内容请访问
https://download.csdn.net/download/xiaoxingkongyuxi/90248304
https://download.csdn.net/download/xiaoxingkongyuxi/90248304
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐

所有评论(0)