本文介绍如何实现进销存管理系统的业务单据模块,业务单据模块包括采购进货单、采购退货单、销售出货单、销售退货单4个菜单页面。由于进销单据字段大同小异,因此设计共用一个页面组件类。

1. 配置模块

运行项目,在【系统管理-模块管理】中配置如下模块菜单,配置教程参考之前的教程。

一级模块 二级模块 代码 图标 Url 描述
进货管理 Import import
采购进货单 ImportList unordered-list /bms/ImportList 查询和维护采购进货单信息。
采购退货单 ImportReturn unordered-list /bms/ImportReturn 查询和维护采购退货单信息。
销货管理 Export export
销售出货单 ExportList unordered-list /bms/ExportList 查询和维护销售出货单信息。
销售退货单 ExportReturn unordered-list /bms/ExportReturn 查询和维护销售退货单信息。

2. 实体类

JxcLite项目Entities文件夹下面添加JxBillHead.csJxBillList.cs两个实体类文件,实体类代码可以直接复制模块管理中由模型设置生成的代码。文章中只简单描述一下实体类的定义,具体代码参见开源,代码定义如下:

namespace JxcLite.Entities;

/// <summary>
/// 业务单据表头信息类。
/// </summary>
public class JxBillHead : EntityBase { } /// <summary>
/// 业务单据表体信息类。
/// </summary>
public class JxBillList : EntityBase { }

3. 建表脚本

打开JxcLite.Web项目Resources文件夹下的Tables.sql资源文件,复制粘贴由【模块管理-模型设置】中生成的建表脚本。文章中只简单描述一下建表脚本,具体脚本参见开源,内容如下:

CREATE TABLE [JxBillHead] (
[Id] varchar(50) NOT NULL PRIMARY KEY,
...
[Files] nvarchar(500) NULL
); CREATE TABLE [JxBillList] (
[Id] varchar(50) NOT NULL PRIMARY KEY,
...
[Note] ntext NULL
);

4. 服务接口

JxcLite项目Services文件夹下面添加业务单据模块服务接口,文件名定义为IBillService.cs,该接口定义前后端交互的Api访问方法,包括分页查询、批量删除实体、保存实体。具体方法定义如下:

namespace JxcLite.Services;

public interface IBillService : IService
{
//分页查询业务单据信息
Task<PagingResult<JxBillHead>> QueryBillsAsync(PagingCriteria criteria);
//根据单据类型获取默认单据信息
Task<JxBillHead> GetDefaultBillAsync(string type);
//根据表头ID获取单据表体信息列表
Task<List<JxBillList>> GetBillListsAsync(string headId);
//批量删除业务单据信息
Task<Result> DeleteBillsAsync(List<JxBillHead> models);
//保存业务单据信息
Task<Result> SaveBillAsync(UploadInfo<JxBillHead> info);
}

5. 服务实现

JxcLite.Web项目Services文件夹下面添加业务单据模块服务接口的实现类,文件名定义为BillService.cs,文章中只简单描述一下实现类的定义和继承,具体实现参见开源,定义如下:

namespace JxcLite.Web.Services;

class BillService(Context context) : ServiceBase(context), IBaseDataService
{
public Task<PagingResult<JxBillHead>> QueryBillsAsync(PagingCriteria criteria) { }
public Task<JxBillHead> GetDefaultBillAsync(string type) { }
public Task<List<JxBillList>> GetBillListsAsync(string headId) { }
public Task<Result> DeleteBillsAsync(List<JxBillHead> models) { }
public Task<Result> SaveBillAsync(UploadInfo<JxBillHead> info) { }
}

双击打开JxcLite.Web项目中的AppWeb.cs文件,在AddJxcLiteCore方法中注册服务类,前端组件可以通过依赖注入工厂创建服务的实例。代码如下:

public static class AppWeb
{
public static void AddJxcLiteCore(this IServiceCollection services)
{
services.AddScoped<IBillService, BillService>();
}
}

6. 数据依赖

JxcLite.Web项目Repositories文件夹下面添加业务单据模块数据依赖类,文件名定义为BillRepository.cs,文章中只简单描述一下依赖类的定义,具体实现参见开源,定义如下:

namespace JxcLite.Web.Repositories;

class BillRepository
{
internal static Task<PagingResult<JxBillHead>> QueryBillsAsync(Database db, PagingCriteria criteria) { } internal static Task<List<JxBillList>> GetBillListsAsync(Database db, string headId) { }
//根据前缀获取最大业务单号
internal static Task<string> GetMaxBillNoAsync(Database db, string prefix) { }
}

7. 列表页面

JxcLite.Client项目Pages\BillData文件夹下面添加BillList.cs单据列表组件,该组件是进销单及退货单的列表组件共用类,具体实现参见开源,部分代码如下:

namespace JxcLite.Client.Pages.BillData;

public class BillList : BaseTablePage<JxBillHead>
{
private IBillService Service;
//取得业务单据类型(进货、进退货、销货、销退货),由具体单据页面重写该类型
protected virtual string Type { get; } protected override async Task OnPageInitAsync()
{
await base.OnPageInitAsync();
Service = await CreateServiceAsync<IBillService>();//创建服务
Table.FormType = typeof(BillForm);//自定义表单类型
Table.OnQuery = QueryBillsAsync; //查询方法
//下面是设置列表栏位显示的模板
Table.Column(c => c.Status).Template((b, r) => b.Tag(r.Status));
Table.Column(c => c.BillDate).Type(FieldType.Date);
}
//新增
public async void New()
{
var row = await Service.GetDefaultBillAsync(Type);
Table.NewForm(Service.SaveBillAsync, row);
}
//编辑
public async void Edit(JxBillHead row)
{
row.Lists = await Service.GetBillListsAsync(row.Id);
Table.EditForm(Service.SaveBillAsync, row);
}
//批量删除和删除
public void DeleteM() => Table.DeleteM(Service.DeleteBillsAsync);
public void Delete(JxBillHead row) => Table.Delete(Service.DeleteBillsAsync, row);
//复制和退货
public void Copy() => Table.SelectRow(async row => {});
public void Return() => Table.SelectRow(async row => {});
//打印
public void Print() => Table.SelectRow(async row =>
{
row.Lists = await Service.GetBillListsAsync(row.Id);
//BillPrint为业务单据打印组件
await JS.PrintAsync<BillPrint>(f => f.Set(c => c.Model, row));
});
//导出
public async void Export() => await ExportDataAsync(); private Task<PagingResult<JxBillHead>> QueryBillsAsync(PagingCriteria criteria)
{
//设置单据类型查询条件
criteria.SetQuery(nameof(JxBillHead.Type), QueryType.Equal, Type);
return Service.QueryBillsAsync(criteria);
}
}

8. 供应商和客户选择框

JxcLite.Client项目Shared文件夹下面添加PartnerPicker.cs,该组件继承BasePicker,用于弹窗选择客户和供应商信息,具体实现参见开源,部分代码如下:

namespace JxcLite.Client.Shared;

public class PartnerPicker : BasePicker<JxPartner>
{
private IBaseDataService Service;
private TableModel<JxPartner> Table;
//取得弹框选择的数据列表
public override List<JxPartner> SelectedItems => Table.SelectedRows?.ToList();
//取得或设置商业伙伴类型(客户、供应商)
[Parameter] public string Type { get; set; } protected override async Task OnInitAsync() {}
protected override void BuildContent(RenderTreeBuilder builder) => builder.Table(Table);
}

9. 商品信息选择框

JxcLite.Client项目Shared文件夹下面添加GoodsPicker.cs,该组件继承BasePicker,用于弹窗选择商品信息,具体实现参见开源,部分代码如下:

namespace JxcLite.Client.Shared;

public class GoodsPicker : BasePicker<JxGoods>
{
private IBaseDataService Service;
private TableModel<JxGoods> Table;
//取得弹框选择的数据列表
public override List<JxGoods> SelectedItems => Table.SelectedRows?.ToList(); protected override async Task OnInitAsync() {}
protected override void BuildContent(RenderTreeBuilder builder) => builder.Table(Table);
}

10. 表单组件

首先在JxcLite.Client项目Shared文件夹下面添加TypeForms.csTypeTables.cs文件,添加业务单据表头类型表单组件和业务单据表体类型表格组件,代码如下:

namespace JxcLite.Client.Shared;

public class BillHeadTypeForm : AntForm<JxBillHead> { }

public class BillListTypeTable : AntTable<JxBillList> { }

再在JxcLite.Client项目Pages\BillData文件夹下面添加BillForm.razorBillForm.razor.cs文件,由于单据表单组件有点复杂,代码较长,所以采用razor语法来实现,该组件是进销单及退货单的列表组件共用类,具体实现参见开源,部分代码如下:

@inherits BaseForm<JxBillHead>

<BillHeadTypeForm Form="Model">
<AntRow>
<DataItem Span="6" Label="业务单号" Required>
<AntInput Disabled @bind-Value="@context.BillNo" />
</DataItem>
<DataItem Span="6" Label="单证状态">
<KTag Text="@context.Status" />
</DataItem>
<DataItem Span="6" Label="单证日期" Required>
<AntDatePicker @bind-Value="@context.BillDate" />
</DataItem>
<DataItem Span="6" Label="商业伙伴" Required>
<PartnerPicker Value="@context.Partner" AllowClear
Type="@GetPartnerPickerType(context)" />
</DataItem>
</AntRow>
</BillHeadTypeForm>
<KToolbar>
<KTitle Text="商品明细" />
<div>
@if (!Model.IsView)
{
<Button Type="@ButtonType.Primary" Icon="plus" OnClick="OnAdd">添加</Button>
}
</div>
</KToolbar>
<BillListTypeTable DataSource="Model.Data.Lists" HidePagination ScrollX="1300px" ScrollY="200px">
<IntegerColumn Title="序号" Field="@context.SeqNo" Width="60" Fixed="left" />
<StringColumn Title="商品编码" Width="120" Fixed="left">
<AntInput @bind-Value="@context.Code" Style="width:100px" />
</StringColumn>
<StringColumn Title="金额" Width="100">
<AntDecimal @bind-Value="@context.Amount" OnChange="e=>OnGoodsChange(3, context)" />
</StringColumn>
@if (!Model.IsView)
{
<ActionColumn Title="操作" Align="ColumnAlign.Center" Width="100" Fixed="right">
<Tag Color="red-inverse" OnClick="e=>OnDelete(context)">删除</Tag>
</ActionColumn>
}
<SummaryRow>
<SummaryCell Fixed="left">合计</SummaryCell>
<SummaryCell>@Model.Data.Lists.Sum(l => l.Amount)</SummaryCell>
<SummaryCell />
@if (!Model.IsView)
{
<SummaryCell />
}
</SummaryRow>
</BillListTypeTable>
namespace JxcLite.Client.Pages.BillData;

partial class BillForm
{
private KUpload upload;
private static string GetPartnerPickerType(JxBillHead model) {}
private async void OnFilesChanged(List<FileDataInfo> files) {}
private void OnAdd() {}
private void OnDelete(JxBillList row) => Model.Data.Lists.Remove(row);
private void OnGoodsChange(int field, JxBillList row) {}
}

11. 打印组件

JxcLite.Client项目Pages\BillData文件夹下面添加BillPrint.cs,该组件是打印业务单据内容组件,具体实现参见开源,部分代码如下:

namespace JxcLite.Client.Pages.BillData;

class BillPrint : ComponentBase
{
//业务单据实体对象
[Parameter] public JxBillHead Model { get; set; } protected override void BuildRenderTree(RenderTreeBuilder builder)
{
BuildStyle(builder);//构建样式表,打印时调用浏览器的预览,选打印机打印
BuildForm(builder); //构建打印表单
} private static void BuildStyle(RenderTreeBuilder builder)
{
builder.Markup(@"<style>
.bill-print {position:relative;}
</style>");
} private void BuildForm(RenderTreeBuilder builder) {}
}

Known框架实战演练——进销存业务单据的更多相关文章

  1. 文献综述十八:基于SSH框架的进销存管理系统设计与实现

    一.基本信息 标题:基于SSH框架的进销存管理系统设计与实现 时间:2017 出版源:内蒙古科技与经济 文件分类:对框架的研究 二.研究背景 进销存管理系统在各企业中广泛应用,使用SSH框架,很大程度 ...

  2. Odoo进销存业务思路浅析

    转载请注明原文地址:https://www.cnblogs.com/cnodoo/p/9307485.html  一:采购业务(进) 1:根据采购对象和性质,采购业务主要分为四类: 生产性采购:采购企 ...

  3. PDA手持机 移动开单进销存系统 现场出打印凭据和扫码 新的亮点

    传统车销模式弊端:1.手写开单,效率低,动作慢2.现场手写开单明细不能打印,产品明细不规范3.电脑办公人员及车销人员对车上的库存情况掌握不清楚,销售人员对每种产品销售价格不清楚4.老板对员工工作的管控 ...

  4. 改变传统的开单模式------手持POS终端移动销售开单 移动进销存的利器

    手持POS终端高清彩屏,清晰.美观.大方,适用于仓库.超市.服装.食品.批发零售.手机电脑等企业管理.可与管理软件灵活对接.1:员工记不住价格,产品名称,只要有PDA扫描,价格,库存,直接开销售单,打 ...

  5. C# WINFORM进销存系统开发(内涵免费源码+部分实操视频讲解)

    互联网的时代,电商火爆,大家都开始进行线上销售货品,那你是如何管理你的商品库存和进销问题?软积木--小敏用的是C# WINFORM进销存系统来管理我的数据,给我带来了很多便利. 它是高频需求项目,很多 ...

  6. 浩瀚技术团队... 安卓智能POS移动PDA开单器 开单器 进销存系统 进销存系统

    浩瀚技术团队... 智能POS移动PDA开单器 开单器 进销存系统 进销存系统 点餐 会员管理 会员管理 深度解读 手机APP移动办公到底是什么? 快速打单POS·不仅仅是快那么简单!  

  7. 寒冬之下,浩瀚智能开单收银打印扫描POS为何能在批发零售门店商场 车销行业 风靡!:进销存+打印扫描POS机

    是一款适用于商超.餐饮.服装鞋帽.家电专营等等具有零售行业特点的企业,供企业管理人员用于管理.监控本品牌的市场占有率.门店覆盖区域.网点分布合理性等经济地理信息的工具平台. 1,功能一:业务抄单文章来 ...

  8. 【.NET实战教程】北风网基于ASP.NET多层架构下的企业级进销存软件全程培训

    .Net进销存系统详细课程大纲(开发工具采用VS2008+sqlsever2005) [小编提醒:现在学习的话,可以使用vs2012+sql 2008 学习的是思路,教学环境不一定要一模一样]1.项目 ...

  9. 一秒钟看懂SaaS、CRM、OA、ERP、HR、进销存

    自2014年以来,SaaS.CRM.OA.ERP.HR.APM.进销存.财务系统等,这些名词大量出现在微信朋友圈.电视楼宇广告和千百万融资资讯中.它们到底是什么意思?相互之间又有什么区别?在这个飞速发 ...

  10. 浩瀚技术助力批发零售商户实现PDA移动POS打印扫描进销存信息化管理

    批发零售商户其各门店销售品种多,销售量大,在市场上占据巨大的份额,随着各门店的不断扩展,基层的销售管理并不尽如意,传统的进销存管理软件安装在PC端,无法满足有现有的业务支撑,面对当前现状,移动进销存管 ...

随机推荐

  1. 来自多彩世界的控制台——C#控制台输出彩色字符画

    引言 看到酷安上有这样一个活动,萌生了用 C# 生成字符画的想法,先放出原图.   酷安手绘牛啤     §1 黑白 将图像转换成字符画在 C# 中很简单,思路大致如下: 加载图像,逐像素提取明度. ...

  2. 微软的文本转语音服务Microsoft.CognitiveServices.Speech

    微软的Edge 浏览器里的大声朗读里-"晓晓" 很接近自然人,比起其它平台的强很多. 在AZURE 可免费体验,每月限额50万字,每个语音转换不超过10分钟长度. C# 调用: u ...

  3. .net core C# DataTable 和List之间相互转换的方法

    一.List<T>/IEnumerable转换到DataTable/DataView 方法一: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 1 ...

  4. 【Java编程教程】详解Java 中的对象和类

    在本页中,我们将了解 Java 对象和类.在面向对象的编程技术中,我们使用对象和类来设计程序. Java中的对象既是物理实体又是逻辑实体,而Java中的类只是逻辑实体. 什么是Java中的对象 具有状 ...

  5. Java中try catch finally 关键字

    异常处理中的几个常用关键字(try catch finally throw throws) 异常处理 java中提供一套异常处理机制,在程序发生异常时,可以执行预先设定好的处理程序, 执行完成后,程序 ...

  6. kettle从入门到精通 第五十六课 ETL之kettle Microsoft Excel Output

    1.9.4 版本的kettle中有两个Excel输出,Excel输出和Microsoft Excel输出.前者只支持xls格式,后者支持xls和xlsx两种格式,本节课主要讲解步骤Microsoft ...

  7. Python BeautifulSoup定位取值

    -*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* ...

  8. 喜讯!INFINI Easysearch 在墨天轮搜索型数据库排名中荣登榜首

    近日,2023 年 9 月的 墨天轮中国数据库流行度排行 火热出炉,本月共有 287 个数据库参与排名,中国数据库行业竞争日益激烈.其中,极限科技旗下软件产品 INFINI Easysearch 在 ...

  9. 命运2 Cross Save

    epic 上免费领的命运2,进不去,界面提示要扫码. 解决方法: 1.手机或电脑浏览器进入:https://www.bungie.net/. 2.使用epic 账号登录 ,然后设置一个邮箱,邮箱收到验 ...

  10. MySQL数据库开发(1)

    数据库的概述 1 什么是数据(Data) 描述事物的符号记录称为数据,描述事物的符号既可以是数字,也可以是文字.图片,图像.声音.语言等,数据由多种表现形式, 它们都可以经过数字化后存入计算机. 在计 ...