Initial commit
Initial commit til Git. V2 er deployed
This commit is contained in:
362
PointOfSale/.gitignore
vendored
Normal file
362
PointOfSale/.gitignore
vendored
Normal file
@@ -0,0 +1,362 @@
|
|||||||
|
## Ignore Visual Studio temporary files, build results, and
|
||||||
|
## files generated by popular Visual Studio add-ons.
|
||||||
|
##
|
||||||
|
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
|
||||||
|
|
||||||
|
# User-specific files
|
||||||
|
*.rsuser
|
||||||
|
*.suo
|
||||||
|
*.user
|
||||||
|
*.userosscache
|
||||||
|
*.sln.docstates
|
||||||
|
|
||||||
|
# User-specific files (MonoDevelop/Xamarin Studio)
|
||||||
|
*.userprefs
|
||||||
|
|
||||||
|
# Mono auto generated files
|
||||||
|
mono_crash.*
|
||||||
|
|
||||||
|
# Build results
|
||||||
|
[Dd]ebug/
|
||||||
|
[Dd]ebugPublic/
|
||||||
|
[Rr]elease/
|
||||||
|
[Rr]eleases/
|
||||||
|
x64/
|
||||||
|
x86/
|
||||||
|
[Ww][Ii][Nn]32/
|
||||||
|
[Aa][Rr][Mm]/
|
||||||
|
[Aa][Rr][Mm]64/
|
||||||
|
bld/
|
||||||
|
[Bb]in/
|
||||||
|
[Oo]bj/
|
||||||
|
[Ll]og/
|
||||||
|
[Ll]ogs/
|
||||||
|
|
||||||
|
# Visual Studio 2015/2017 cache/options directory
|
||||||
|
.vs/
|
||||||
|
# Uncomment if you have tasks that create the project's static files in wwwroot
|
||||||
|
#wwwroot/
|
||||||
|
|
||||||
|
# Visual Studio 2017 auto generated files
|
||||||
|
Generated\ Files/
|
||||||
|
|
||||||
|
# MSTest test Results
|
||||||
|
[Tt]est[Rr]esult*/
|
||||||
|
[Bb]uild[Ll]og.*
|
||||||
|
|
||||||
|
# NUnit
|
||||||
|
*.VisualState.xml
|
||||||
|
TestResult.xml
|
||||||
|
nunit-*.xml
|
||||||
|
|
||||||
|
# Build Results of an ATL Project
|
||||||
|
[Dd]ebugPS/
|
||||||
|
[Rr]eleasePS/
|
||||||
|
dlldata.c
|
||||||
|
|
||||||
|
# Benchmark Results
|
||||||
|
BenchmarkDotNet.Artifacts/
|
||||||
|
|
||||||
|
# .NET Core
|
||||||
|
project.lock.json
|
||||||
|
project.fragment.lock.json
|
||||||
|
artifacts/
|
||||||
|
|
||||||
|
# ASP.NET Scaffolding
|
||||||
|
ScaffoldingReadMe.txt
|
||||||
|
|
||||||
|
# StyleCop
|
||||||
|
StyleCopReport.xml
|
||||||
|
|
||||||
|
# Files built by Visual Studio
|
||||||
|
*_i.c
|
||||||
|
*_p.c
|
||||||
|
*_h.h
|
||||||
|
*.ilk
|
||||||
|
*.meta
|
||||||
|
*.obj
|
||||||
|
*.iobj
|
||||||
|
*.pch
|
||||||
|
*.pdb
|
||||||
|
*.ipdb
|
||||||
|
*.pgc
|
||||||
|
*.pgd
|
||||||
|
*.rsp
|
||||||
|
*.sbr
|
||||||
|
*.tlb
|
||||||
|
*.tli
|
||||||
|
*.tlh
|
||||||
|
*.tmp
|
||||||
|
*.tmp_proj
|
||||||
|
*_wpftmp.csproj
|
||||||
|
*.log
|
||||||
|
*.vspscc
|
||||||
|
*.vssscc
|
||||||
|
.builds
|
||||||
|
*.pidb
|
||||||
|
*.svclog
|
||||||
|
*.scc
|
||||||
|
|
||||||
|
# Chutzpah Test files
|
||||||
|
_Chutzpah*
|
||||||
|
|
||||||
|
# Visual C++ cache files
|
||||||
|
ipch/
|
||||||
|
*.aps
|
||||||
|
*.ncb
|
||||||
|
*.opendb
|
||||||
|
*.opensdf
|
||||||
|
*.sdf
|
||||||
|
*.cachefile
|
||||||
|
*.VC.db
|
||||||
|
*.VC.VC.opendb
|
||||||
|
|
||||||
|
# Visual Studio profiler
|
||||||
|
*.psess
|
||||||
|
*.vsp
|
||||||
|
*.vspx
|
||||||
|
*.sap
|
||||||
|
|
||||||
|
# Visual Studio Trace Files
|
||||||
|
*.e2e
|
||||||
|
|
||||||
|
# TFS 2012 Local Workspace
|
||||||
|
$tf/
|
||||||
|
|
||||||
|
# Guidance Automation Toolkit
|
||||||
|
*.gpState
|
||||||
|
|
||||||
|
# ReSharper is a .NET coding add-in
|
||||||
|
_ReSharper*/
|
||||||
|
*.[Rr]e[Ss]harper
|
||||||
|
*.DotSettings.user
|
||||||
|
|
||||||
|
# TeamCity is a build add-in
|
||||||
|
_TeamCity*
|
||||||
|
|
||||||
|
# DotCover is a Code Coverage Tool
|
||||||
|
*.dotCover
|
||||||
|
|
||||||
|
# AxoCover is a Code Coverage Tool
|
||||||
|
.axoCover/*
|
||||||
|
!.axoCover/settings.json
|
||||||
|
|
||||||
|
# Coverlet is a free, cross platform Code Coverage Tool
|
||||||
|
coverage*.json
|
||||||
|
coverage*.xml
|
||||||
|
coverage*.info
|
||||||
|
|
||||||
|
# Visual Studio code coverage results
|
||||||
|
*.coverage
|
||||||
|
*.coveragexml
|
||||||
|
|
||||||
|
# NCrunch
|
||||||
|
_NCrunch_*
|
||||||
|
.*crunch*.local.xml
|
||||||
|
nCrunchTemp_*
|
||||||
|
|
||||||
|
# MightyMoose
|
||||||
|
*.mm.*
|
||||||
|
AutoTest.Net/
|
||||||
|
|
||||||
|
# Web workbench (sass)
|
||||||
|
.sass-cache/
|
||||||
|
|
||||||
|
# Installshield output folder
|
||||||
|
[Ee]xpress/
|
||||||
|
|
||||||
|
# DocProject is a documentation generator add-in
|
||||||
|
DocProject/buildhelp/
|
||||||
|
DocProject/Help/*.HxT
|
||||||
|
DocProject/Help/*.HxC
|
||||||
|
DocProject/Help/*.hhc
|
||||||
|
DocProject/Help/*.hhk
|
||||||
|
DocProject/Help/*.hhp
|
||||||
|
DocProject/Help/Html2
|
||||||
|
DocProject/Help/html
|
||||||
|
|
||||||
|
# Click-Once directory
|
||||||
|
publish/
|
||||||
|
|
||||||
|
# Publish Web Output
|
||||||
|
*.[Pp]ublish.xml
|
||||||
|
*.azurePubxml
|
||||||
|
# Note: Comment the next line if you want to checkin your web deploy settings,
|
||||||
|
# but database connection strings (with potential passwords) will be unencrypted
|
||||||
|
*.pubxml
|
||||||
|
*.publishproj
|
||||||
|
|
||||||
|
# Microsoft Azure Web App publish settings. Comment the next line if you want to
|
||||||
|
# checkin your Azure Web App publish settings, but sensitive information contained
|
||||||
|
# in these scripts will be unencrypted
|
||||||
|
PublishScripts/
|
||||||
|
|
||||||
|
# NuGet Packages
|
||||||
|
*.nupkg
|
||||||
|
# NuGet Symbol Packages
|
||||||
|
*.snupkg
|
||||||
|
# The packages folder can be ignored because of Package Restore
|
||||||
|
**/[Pp]ackages/*
|
||||||
|
# except build/, which is used as an MSBuild target.
|
||||||
|
!**/[Pp]ackages/build/
|
||||||
|
# Uncomment if necessary however generally it will be regenerated when needed
|
||||||
|
#!**/[Pp]ackages/repositories.config
|
||||||
|
# NuGet v3's project.json files produces more ignorable files
|
||||||
|
*.nuget.props
|
||||||
|
*.nuget.targets
|
||||||
|
|
||||||
|
# Microsoft Azure Build Output
|
||||||
|
csx/
|
||||||
|
*.build.csdef
|
||||||
|
|
||||||
|
# Microsoft Azure Emulator
|
||||||
|
ecf/
|
||||||
|
rcf/
|
||||||
|
|
||||||
|
# Windows Store app package directories and files
|
||||||
|
AppPackages/
|
||||||
|
BundleArtifacts/
|
||||||
|
Package.StoreAssociation.xml
|
||||||
|
_pkginfo.txt
|
||||||
|
*.appx
|
||||||
|
*.appxbundle
|
||||||
|
*.appxupload
|
||||||
|
|
||||||
|
# Visual Studio cache files
|
||||||
|
# files ending in .cache can be ignored
|
||||||
|
*.[Cc]ache
|
||||||
|
# but keep track of directories ending in .cache
|
||||||
|
!?*.[Cc]ache/
|
||||||
|
|
||||||
|
# Others
|
||||||
|
ClientBin/
|
||||||
|
~$*
|
||||||
|
*~
|
||||||
|
*.dbmdl
|
||||||
|
*.dbproj.schemaview
|
||||||
|
*.jfm
|
||||||
|
*.pfx
|
||||||
|
*.publishsettings
|
||||||
|
orleans.codegen.cs
|
||||||
|
|
||||||
|
# Including strong name files can present a security risk
|
||||||
|
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
|
||||||
|
#*.snk
|
||||||
|
|
||||||
|
# Since there are multiple workflows, uncomment next line to ignore bower_components
|
||||||
|
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
|
||||||
|
#bower_components/
|
||||||
|
|
||||||
|
# RIA/Silverlight projects
|
||||||
|
Generated_Code/
|
||||||
|
|
||||||
|
# Backup & report files from converting an old project file
|
||||||
|
# to a newer Visual Studio version. Backup files are not needed,
|
||||||
|
# because we have git ;-)
|
||||||
|
_UpgradeReport_Files/
|
||||||
|
Backup*/
|
||||||
|
UpgradeLog*.XML
|
||||||
|
UpgradeLog*.htm
|
||||||
|
ServiceFabricBackup/
|
||||||
|
*.rptproj.bak
|
||||||
|
|
||||||
|
# SQL Server files
|
||||||
|
*.mdf
|
||||||
|
*.ldf
|
||||||
|
*.ndf
|
||||||
|
|
||||||
|
# Business Intelligence projects
|
||||||
|
*.rdl.data
|
||||||
|
*.bim.layout
|
||||||
|
*.bim_*.settings
|
||||||
|
*.rptproj.rsuser
|
||||||
|
*- [Bb]ackup.rdl
|
||||||
|
*- [Bb]ackup ([0-9]).rdl
|
||||||
|
*- [Bb]ackup ([0-9][0-9]).rdl
|
||||||
|
|
||||||
|
# Microsoft Fakes
|
||||||
|
FakesAssemblies/
|
||||||
|
|
||||||
|
# GhostDoc plugin setting file
|
||||||
|
*.GhostDoc.xml
|
||||||
|
|
||||||
|
# Node.js Tools for Visual Studio
|
||||||
|
.ntvs_analysis.dat
|
||||||
|
node_modules/
|
||||||
|
|
||||||
|
# Visual Studio 6 build log
|
||||||
|
*.plg
|
||||||
|
|
||||||
|
# Visual Studio 6 workspace options file
|
||||||
|
*.opt
|
||||||
|
|
||||||
|
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
|
||||||
|
*.vbw
|
||||||
|
|
||||||
|
# Visual Studio LightSwitch build output
|
||||||
|
**/*.HTMLClient/GeneratedArtifacts
|
||||||
|
**/*.DesktopClient/GeneratedArtifacts
|
||||||
|
**/*.DesktopClient/ModelManifest.xml
|
||||||
|
**/*.Server/GeneratedArtifacts
|
||||||
|
**/*.Server/ModelManifest.xml
|
||||||
|
_Pvt_Extensions
|
||||||
|
|
||||||
|
# Paket dependency manager
|
||||||
|
.paket/paket.exe
|
||||||
|
paket-files/
|
||||||
|
|
||||||
|
# FAKE - F# Make
|
||||||
|
.fake/
|
||||||
|
|
||||||
|
# CodeRush personal settings
|
||||||
|
.cr/personal
|
||||||
|
|
||||||
|
# Python Tools for Visual Studio (PTVS)
|
||||||
|
__pycache__/
|
||||||
|
*.pyc
|
||||||
|
|
||||||
|
# Cake - Uncomment if you are using it
|
||||||
|
# tools/**
|
||||||
|
# !tools/packages.config
|
||||||
|
|
||||||
|
# Tabs Studio
|
||||||
|
*.tss
|
||||||
|
|
||||||
|
# Telerik's JustMock configuration file
|
||||||
|
*.jmconfig
|
||||||
|
|
||||||
|
# BizTalk build output
|
||||||
|
*.btp.cs
|
||||||
|
*.btm.cs
|
||||||
|
*.odx.cs
|
||||||
|
*.xsd.cs
|
||||||
|
|
||||||
|
# OpenCover UI analysis results
|
||||||
|
OpenCover/
|
||||||
|
|
||||||
|
# Azure Stream Analytics local run output
|
||||||
|
ASALocalRun/
|
||||||
|
|
||||||
|
# MSBuild Binary and Structured Log
|
||||||
|
*.binlog
|
||||||
|
|
||||||
|
# NVidia Nsight GPU debugger configuration file
|
||||||
|
*.nvuser
|
||||||
|
|
||||||
|
# MFractors (Xamarin productivity tool) working folder
|
||||||
|
.mfractor/
|
||||||
|
|
||||||
|
# Local History for Visual Studio
|
||||||
|
.localhistory/
|
||||||
|
|
||||||
|
# BeatPulse healthcheck temp database
|
||||||
|
healthchecksdb
|
||||||
|
|
||||||
|
# Backup folder for Package Reference Convert tool in Visual Studio 2017
|
||||||
|
MigrationBackup/
|
||||||
|
|
||||||
|
# Ionide (cross platform F# VS Code tools) working folder
|
||||||
|
.ionide/
|
||||||
|
|
||||||
|
# Fody - auto-generated XML schema
|
||||||
|
FodyWeavers.xsd
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using EpsonPrinter.Model;
|
||||||
|
using EpsonPrinter.Services;
|
||||||
|
|
||||||
|
namespace EpsonPrinter.Controllers
|
||||||
|
{
|
||||||
|
[Route("api/[controller]")]
|
||||||
|
[ApiController]
|
||||||
|
public class PosPrinterController : ControllerBase
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// PrintReceipt receipt, so far only for all Epson Thermal Printers
|
||||||
|
/// </summary>
|
||||||
|
/// PrintStyle is:
|
||||||
|
/// None
|
||||||
|
/// FontB
|
||||||
|
/// Bold
|
||||||
|
/// DoubleHeight
|
||||||
|
/// DoubleWidth
|
||||||
|
/// Underline
|
||||||
|
/// There is support for any combination of PrintStyles
|
||||||
|
/// ----------------------------------------
|
||||||
|
///
|
||||||
|
///
|
||||||
|
/// <param name="receiptModel"></param>
|
||||||
|
[HttpPost]
|
||||||
|
[Route("Receipt")]
|
||||||
|
public void PrintReceipt([FromServices] EpsonPrintService epsonPrint, ReceiptModel receiptModel)
|
||||||
|
{
|
||||||
|
epsonPrint.PrintReceipt(receiptModel);
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPost]
|
||||||
|
[Route("SaleOfDay")]
|
||||||
|
public void PrintSaleOfDay([FromServices] EpsonPrintService epsonPrint, SaleOfDayModel saleOfDayModel)
|
||||||
|
{
|
||||||
|
epsonPrint.PrintSaleOfDay(saleOfDayModel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
|
||||||
|
namespace EpsonPrinter.Controllers
|
||||||
|
{
|
||||||
|
[Route("api/[controller]")]
|
||||||
|
[ApiController]
|
||||||
|
public class ValuesController : ControllerBase
|
||||||
|
{
|
||||||
|
[HttpGet]
|
||||||
|
[Route("HelloWorld")]
|
||||||
|
public string Get()
|
||||||
|
{
|
||||||
|
return "HelloWorld";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
9
PointOfSale/EpsonPrinterLinux/Enums/AlignmentEnum.cs
Normal file
9
PointOfSale/EpsonPrinterLinux/Enums/AlignmentEnum.cs
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
namespace EpsonPrinter.Enums
|
||||||
|
{
|
||||||
|
public enum AlignmentEnum
|
||||||
|
{
|
||||||
|
Left,
|
||||||
|
Center,
|
||||||
|
Right
|
||||||
|
}
|
||||||
|
}
|
||||||
12
PointOfSale/EpsonPrinterLinux/Enums/PrintStylesEnum.cs
Normal file
12
PointOfSale/EpsonPrinterLinux/Enums/PrintStylesEnum.cs
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
namespace EpsonPrinter.Enums
|
||||||
|
{
|
||||||
|
public enum PrintStylesEnum
|
||||||
|
{
|
||||||
|
None,
|
||||||
|
FontB,
|
||||||
|
Bold,
|
||||||
|
DoubleHeight,
|
||||||
|
DoubleWidth,
|
||||||
|
UnderLine
|
||||||
|
}
|
||||||
|
}
|
||||||
22
PointOfSale/EpsonPrinterLinux/EpsonPrinter.csproj
Normal file
22
PointOfSale/EpsonPrinterLinux/EpsonPrinter.csproj
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
|
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
|
||||||
|
<DockerfileContext>..\Pos</DockerfileContext>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Remove="ESC-POS\**" />
|
||||||
|
<Content Remove="ESC-POS\**" />
|
||||||
|
<EmbeddedResource Remove="ESC-POS\**" />
|
||||||
|
<None Remove="ESC-POS\**" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Swashbuckle.AspNetCore" Version="10.1.7" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
18
PointOfSale/EpsonPrinterLinux/Model/BodyModel.cs
Normal file
18
PointOfSale/EpsonPrinterLinux/Model/BodyModel.cs
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace EpsonPrinter.Model
|
||||||
|
{
|
||||||
|
public class BodyModel
|
||||||
|
{
|
||||||
|
public List<BodyProductModel> Products { get; set; }
|
||||||
|
public decimal TotalPrice { get; set; }
|
||||||
|
public decimal TotalVat { get; set; }
|
||||||
|
public int ReceiptNumber { get; set; }
|
||||||
|
public string ReceiptTime { get; set; }
|
||||||
|
public string Staff { get; set; }
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
15
PointOfSale/EpsonPrinterLinux/Model/BodyProductModel.cs
Normal file
15
PointOfSale/EpsonPrinterLinux/Model/BodyProductModel.cs
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace EpsonPrinter.Model
|
||||||
|
{
|
||||||
|
public class BodyProductModel
|
||||||
|
{
|
||||||
|
public string Product { get; set; }
|
||||||
|
public int NoOfProduct { get; set; }
|
||||||
|
public decimal Price { get; set; }
|
||||||
|
public decimal TotalPrice { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
16
PointOfSale/EpsonPrinterLinux/Model/FooterModel.cs
Normal file
16
PointOfSale/EpsonPrinterLinux/Model/FooterModel.cs
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using EpsonPrinter.Enums;
|
||||||
|
|
||||||
|
namespace EpsonPrinter.Model
|
||||||
|
{
|
||||||
|
public class FooterModel
|
||||||
|
{
|
||||||
|
public string Value { get; set; }
|
||||||
|
public PrintStyleModel PrintStyles { get; set; }
|
||||||
|
public AlignmentEnum TextAlignment { get; set; }
|
||||||
|
public int FeedingLines { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
16
PointOfSale/EpsonPrinterLinux/Model/HeaderModel.cs
Normal file
16
PointOfSale/EpsonPrinterLinux/Model/HeaderModel.cs
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using EpsonPrinter.Enums;
|
||||||
|
|
||||||
|
namespace EpsonPrinter.Model
|
||||||
|
{
|
||||||
|
public class HeaderModel
|
||||||
|
{
|
||||||
|
public string Value { get; set; }
|
||||||
|
public PrintStyleModel PrintStyles { get; set; }
|
||||||
|
public AlignmentEnum TextAlignment { get; set; }
|
||||||
|
public int FeedingLines { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
16
PointOfSale/EpsonPrinterLinux/Model/PrintStyleModel.cs
Normal file
16
PointOfSale/EpsonPrinterLinux/Model/PrintStyleModel.cs
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace EpsonPrinter.Model
|
||||||
|
{
|
||||||
|
public class PrintStyleModel
|
||||||
|
{
|
||||||
|
public bool FontB { get; set; }
|
||||||
|
public bool Bold { get; set; }
|
||||||
|
public bool DoubleHeight { get; set; }
|
||||||
|
public bool DoubleWidth { get; set; }
|
||||||
|
public bool Underline { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
13
PointOfSale/EpsonPrinterLinux/Model/ReceiptModel.cs
Normal file
13
PointOfSale/EpsonPrinterLinux/Model/ReceiptModel.cs
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace EpsonPrinter.Model
|
||||||
|
{
|
||||||
|
public class ReceiptModel
|
||||||
|
{
|
||||||
|
public string LogoBase64 { get; set; }
|
||||||
|
public List<HeaderModel> Header { get; set; }
|
||||||
|
public BodyModel BodyModel { get; set; }
|
||||||
|
public List<FooterModel> Footer { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
10
PointOfSale/EpsonPrinterLinux/Model/SaleOfDayDetail.cs
Normal file
10
PointOfSale/EpsonPrinterLinux/Model/SaleOfDayDetail.cs
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace EpsonPrinter.Model
|
||||||
|
{
|
||||||
|
public class SaleOfDayDetail
|
||||||
|
{
|
||||||
|
public string Category { get; set; }
|
||||||
|
public decimal TotalSale { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
14
PointOfSale/EpsonPrinterLinux/Model/SaleOfDayModel.cs
Normal file
14
PointOfSale/EpsonPrinterLinux/Model/SaleOfDayModel.cs
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace EpsonPrinter.Model
|
||||||
|
{
|
||||||
|
public class SaleOfDayModel
|
||||||
|
{
|
||||||
|
public DateTime Date { get; set; }
|
||||||
|
public int TotalCustomers { get; set; }
|
||||||
|
public Decimal TotalSale { get; set; }
|
||||||
|
public List<SaleOfDayDetail> SaleOfDayDetail { get; set; } = new();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
23
PointOfSale/EpsonPrinterLinux/Program.cs
Normal file
23
PointOfSale/EpsonPrinterLinux/Program.cs
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
using EpsonPrinter.Services;
|
||||||
|
using Microsoft.AspNetCore.Builder;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
|
||||||
|
var builder = WebApplication.CreateBuilder(args);
|
||||||
|
|
||||||
|
// Services
|
||||||
|
builder.Services.AddControllers();
|
||||||
|
builder.Services.AddEndpointsApiExplorer();
|
||||||
|
builder.Services.AddSwaggerGen();
|
||||||
|
|
||||||
|
builder.Services.AddScoped<EpsonPrintService>();
|
||||||
|
|
||||||
|
var app = builder.Build();
|
||||||
|
|
||||||
|
// Swagger (altid aktiv – vi er på en Pi, ikke i produktion)
|
||||||
|
app.UseSwagger();
|
||||||
|
app.UseSwaggerUI();
|
||||||
|
|
||||||
|
// Routing
|
||||||
|
app.MapControllers();
|
||||||
|
|
||||||
|
app.Run();
|
||||||
31
PointOfSale/EpsonPrinterLinux/Properties/launchSettings.json
Normal file
31
PointOfSale/EpsonPrinterLinux/Properties/launchSettings.json
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
{
|
||||||
|
"$schema": "http://json.schemastore.org/launchsettings.json",
|
||||||
|
"iisSettings": {
|
||||||
|
"windowsAuthentication": false,
|
||||||
|
"anonymousAuthentication": true,
|
||||||
|
"iisExpress": {
|
||||||
|
"applicationUrl": "http://localhost:23653",
|
||||||
|
"sslPort": 44334
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"profiles": {
|
||||||
|
"IIS Express": {
|
||||||
|
"commandName": "IISExpress",
|
||||||
|
"launchBrowser": true,
|
||||||
|
"launchUrl": "swagger",
|
||||||
|
"environmentVariables": {
|
||||||
|
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"EpsonPrinter": {
|
||||||
|
"commandName": "Project",
|
||||||
|
"dotnetRunMessages": "true",
|
||||||
|
"launchBrowser": true,
|
||||||
|
"launchUrl": "swagger",
|
||||||
|
"applicationUrl": "https://localhost:5001;http://localhost:5000",
|
||||||
|
"environmentVariables": {
|
||||||
|
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
18
PointOfSale/EpsonPrinterLinux/README_LINUX_USB.txt
Normal file
18
PointOfSale/EpsonPrinterLinux/README_LINUX_USB.txt
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
Linux USB version of the EpsonPrinter API.
|
||||||
|
|
||||||
|
What changed:
|
||||||
|
- Keeps the incoming JSON models for /api/PosPrinter/Receipt and /api/PosPrinter/SaleOfDay
|
||||||
|
- Replaces COM/SerialPrinter transport with raw writes to Linux USB printer device
|
||||||
|
- Uses /dev/usb/lp0 by default from appsettings.json
|
||||||
|
- Builds a standard receipt when parts of the payload are missing
|
||||||
|
- Pulls fallback values from appsettings.json under PrintSettings:Defaults
|
||||||
|
|
||||||
|
Typical run:
|
||||||
|
dotnet restore
|
||||||
|
dotnet run
|
||||||
|
|
||||||
|
Typical endpoint:
|
||||||
|
POST /api/PosPrinter/Receipt
|
||||||
|
|
||||||
|
Important setting:
|
||||||
|
PrintSettings:DevicePath = /dev/usb/lp0
|
||||||
248
PointOfSale/EpsonPrinterLinux/Services/EpsonPrintService.cs
Normal file
248
PointOfSale/EpsonPrinterLinux/Services/EpsonPrintService.cs
Normal file
@@ -0,0 +1,248 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using EpsonPrinter.Model;
|
||||||
|
using Microsoft.Extensions.Configuration;
|
||||||
|
|
||||||
|
namespace EpsonPrinter.Services
|
||||||
|
{
|
||||||
|
public class EpsonPrintService
|
||||||
|
{
|
||||||
|
private readonly IConfiguration _config;
|
||||||
|
private readonly string _devicePath;
|
||||||
|
|
||||||
|
public EpsonPrintService(IConfiguration config)
|
||||||
|
{
|
||||||
|
_config = config;
|
||||||
|
_devicePath = _config["PrintSettings:DevicePath"] ?? "/dev/usb/lp0";
|
||||||
|
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void PrintReceipt(ReceiptModel model)
|
||||||
|
{
|
||||||
|
ICommandEmitter e = new EPSON();
|
||||||
|
InitAndWrite(e);
|
||||||
|
|
||||||
|
List<byte[][]> printBytes = new List<byte[][]>();
|
||||||
|
PrintHeader printHeader = new PrintHeader(e);
|
||||||
|
PrintBody printBody = new PrintBody(e, _config);
|
||||||
|
PrintFooter printFooter = new PrintFooter(e);
|
||||||
|
|
||||||
|
var header = (model.Header != null && model.Header.Any()) ? model.Header : BuildDefaultHeader();
|
||||||
|
var body = model.BodyModel ?? BuildDefaultBody();
|
||||||
|
if (string.IsNullOrWhiteSpace(body.Staff))
|
||||||
|
{
|
||||||
|
body.Staff = _config["PrintSettings:Defaults:Staff"] ?? "Ukendt";
|
||||||
|
}
|
||||||
|
if (string.IsNullOrWhiteSpace(body.ReceiptTime))
|
||||||
|
{
|
||||||
|
body.ReceiptTime = DateTime.Now.ToString("dd-MM-yyyy HH:mm:ss");
|
||||||
|
}
|
||||||
|
if (body.ReceiptNumber <= 0)
|
||||||
|
{
|
||||||
|
body.ReceiptNumber = Math.Abs(Environment.TickCount % 1000000);
|
||||||
|
}
|
||||||
|
body.Products ??= new List<BodyProductModel>();
|
||||||
|
if (!body.Products.Any())
|
||||||
|
{
|
||||||
|
body.Products.Add(new BodyProductModel
|
||||||
|
{
|
||||||
|
Product = "Standard vare",
|
||||||
|
NoOfProduct = 1,
|
||||||
|
Price = 99.00m,
|
||||||
|
TotalPrice = 99.00m
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (body.TotalPrice <= 0)
|
||||||
|
{
|
||||||
|
body.TotalPrice = body.Products.Sum(x => x.TotalPrice <= 0 ? x.Price * x.NoOfProduct : x.TotalPrice);
|
||||||
|
}
|
||||||
|
if (body.TotalVat <= 0)
|
||||||
|
{
|
||||||
|
body.TotalVat = Math.Round(body.TotalPrice * 0.25m, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
var footer = (model.Footer != null && model.Footer.Any()) ? model.Footer : BuildDefaultFooter();
|
||||||
|
|
||||||
|
printBytes.AddRange(printHeader.Print(header));
|
||||||
|
printBytes.AddRange(printBody.Print(body));
|
||||||
|
printBytes.AddRange(printFooter.Print(footer));
|
||||||
|
|
||||||
|
byte[][] array = printBytes.SelectMany(c => c).ToArray();
|
||||||
|
Write(array);
|
||||||
|
Write(e.FeedLines(5));
|
||||||
|
Write(e.FullCut());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void PrintSaleOfDay(SaleOfDayModel model)
|
||||||
|
{
|
||||||
|
ICommandEmitter e = new EPSON();
|
||||||
|
InitAndWrite(e);
|
||||||
|
PrintSaleOfDay(model, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void InitAndWrite(ICommandEmitter e)
|
||||||
|
{
|
||||||
|
Write(e.Initialize());
|
||||||
|
Write(e.Enable());
|
||||||
|
Write(e.CodePage(CodePage.ISO8859_15_LATIN9));
|
||||||
|
Write(e.EnableAutomaticStatusBack());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void PrintSaleOfDay(SaleOfDayModel model, ICommandEmitter e)
|
||||||
|
{
|
||||||
|
List<byte[][]> data = new List<byte[][]>();
|
||||||
|
|
||||||
|
byte[][] dateBytes =
|
||||||
|
{
|
||||||
|
e.SetStyles(PrintStyle.DoubleWidth),
|
||||||
|
e.LeftAlign(),
|
||||||
|
e.PrintLine($"Dato: {model.Date:dd-MM-yyyy}")
|
||||||
|
};
|
||||||
|
data.Add(dateBytes);
|
||||||
|
|
||||||
|
byte[][] seperater =
|
||||||
|
{
|
||||||
|
e.SetStyles(PrintStyle.None),
|
||||||
|
e.LeftAlign(),
|
||||||
|
e.PrintLine("-----------------------------------")
|
||||||
|
};
|
||||||
|
data.Add(seperater);
|
||||||
|
|
||||||
|
foreach (SaleOfDayDetail saleOfDayDetail in model.SaleOfDayDetail)
|
||||||
|
{
|
||||||
|
string pS = $"{saleOfDayDetail.Category} : {saleOfDayDetail.TotalSale.ToString("#.#0", CultureInfo.InvariantCulture)}";
|
||||||
|
byte[][] totalPrice =
|
||||||
|
{
|
||||||
|
e.SetStyles(PrintStyle.DoubleWidth),
|
||||||
|
e.LeftAlign(),
|
||||||
|
e.PrintLine(pS)
|
||||||
|
};
|
||||||
|
data.Add(totalPrice);
|
||||||
|
}
|
||||||
|
|
||||||
|
data.Add(seperater);
|
||||||
|
|
||||||
|
string totalSale = $"Total salg: {model.TotalSale.ToString("#.#0", CultureInfo.InvariantCulture)}";
|
||||||
|
byte[][] tSBytes =
|
||||||
|
{
|
||||||
|
e.SetStyles(PrintStyle.DoubleWidth),
|
||||||
|
e.LeftAlign(),
|
||||||
|
e.PrintLine(totalSale)
|
||||||
|
};
|
||||||
|
data.Add(tSBytes);
|
||||||
|
|
||||||
|
string totalCustomer = $"Antal kunder: {model.TotalCustomers}";
|
||||||
|
byte[][] tCBytes =
|
||||||
|
{
|
||||||
|
e.SetStyles(PrintStyle.DoubleWidth),
|
||||||
|
e.LeftAlign(),
|
||||||
|
e.PrintLine(totalCustomer)
|
||||||
|
};
|
||||||
|
data.Add(tCBytes);
|
||||||
|
|
||||||
|
byte[][] array = data.SelectMany(c => c).ToArray();
|
||||||
|
Write(array);
|
||||||
|
Write(e.FeedLines(5));
|
||||||
|
Write(e.FullCut());
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<HeaderModel> BuildDefaultHeader()
|
||||||
|
{
|
||||||
|
return new List<HeaderModel>
|
||||||
|
{
|
||||||
|
new HeaderModel
|
||||||
|
{
|
||||||
|
Value = _config["PrintSettings:Defaults:StoreName"] ?? "TableTop3D",
|
||||||
|
TextAlignment = Enums.AlignmentEnum.Center,
|
||||||
|
FeedingLines = 0,
|
||||||
|
PrintStyles = new PrintStyleModel { Bold = true, DoubleWidth = true, DoubleHeight = true }
|
||||||
|
},
|
||||||
|
new HeaderModel
|
||||||
|
{
|
||||||
|
Value = _config["PrintSettings:Defaults:AddressLine1"] ?? string.Empty,
|
||||||
|
TextAlignment = Enums.AlignmentEnum.Center,
|
||||||
|
FeedingLines = 0,
|
||||||
|
PrintStyles = new PrintStyleModel { Bold = true }
|
||||||
|
},
|
||||||
|
new HeaderModel
|
||||||
|
{
|
||||||
|
Value = _config["PrintSettings:Defaults:AddressLine2"] ?? string.Empty,
|
||||||
|
TextAlignment = Enums.AlignmentEnum.Center,
|
||||||
|
FeedingLines = 0,
|
||||||
|
PrintStyles = new PrintStyleModel()
|
||||||
|
},
|
||||||
|
new HeaderModel
|
||||||
|
{
|
||||||
|
Value = _config["PrintSettings:Defaults:Cvr"] ?? string.Empty,
|
||||||
|
TextAlignment = Enums.AlignmentEnum.Center,
|
||||||
|
FeedingLines = 1,
|
||||||
|
PrintStyles = new PrintStyleModel()
|
||||||
|
}
|
||||||
|
}.Where(x => !string.IsNullOrWhiteSpace(x.Value)).ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
private FooterModel CreateFooterLine(string value, bool bold = false)
|
||||||
|
{
|
||||||
|
return new FooterModel
|
||||||
|
{
|
||||||
|
Value = value,
|
||||||
|
TextAlignment = Enums.AlignmentEnum.Center,
|
||||||
|
FeedingLines = 0,
|
||||||
|
PrintStyles = new PrintStyleModel { Bold = bold }
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<FooterModel> BuildDefaultFooter()
|
||||||
|
{
|
||||||
|
var values = new[]
|
||||||
|
{
|
||||||
|
_config["PrintSettings:Defaults:FooterLine1"] ?? "Tak for dit køb!",
|
||||||
|
_config["PrintSettings:Defaults:FooterLine2"] ?? string.Empty,
|
||||||
|
_config["PrintSettings:Defaults:Phone"] ?? string.Empty
|
||||||
|
}.Where(x => !string.IsNullOrWhiteSpace(x)).ToList();
|
||||||
|
|
||||||
|
return values.Select((x, i) => CreateFooterLine(x, i == 0)).ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
private BodyModel BuildDefaultBody()
|
||||||
|
{
|
||||||
|
return new BodyModel
|
||||||
|
{
|
||||||
|
ReceiptNumber = Math.Abs(Environment.TickCount % 1000000),
|
||||||
|
ReceiptTime = DateTime.Now.ToString("dd-MM-yyyy HH:mm:ss"),
|
||||||
|
Staff = _config["PrintSettings:Defaults:Staff"] ?? "Ukendt",
|
||||||
|
Products = new List<BodyProductModel>
|
||||||
|
{
|
||||||
|
new BodyProductModel
|
||||||
|
{
|
||||||
|
Product = "Standard vare",
|
||||||
|
NoOfProduct = 1,
|
||||||
|
Price = 99.00m,
|
||||||
|
TotalPrice = 99.00m
|
||||||
|
}
|
||||||
|
},
|
||||||
|
TotalPrice = 99.00m,
|
||||||
|
TotalVat = 24.75m
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Write(byte[] data)
|
||||||
|
{
|
||||||
|
using var stream = new FileStream(_devicePath, FileMode.Open, FileAccess.Write, FileShare.ReadWrite);
|
||||||
|
stream.Write(data, 0, data.Length);
|
||||||
|
stream.Flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Write(byte[][] data)
|
||||||
|
{
|
||||||
|
foreach (var segment in data)
|
||||||
|
{
|
||||||
|
Write(segment);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
24
PointOfSale/EpsonPrinterLinux/Services/PrintAlignment.cs
Normal file
24
PointOfSale/EpsonPrinterLinux/Services/PrintAlignment.cs
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Windows.Input;
|
||||||
|
using EpsonPrinter.Enums;
|
||||||
|
using ESCPOS_NET.Emitters;
|
||||||
|
|
||||||
|
namespace EpsonPrinter.Services
|
||||||
|
{
|
||||||
|
public class PrintAlignment
|
||||||
|
{
|
||||||
|
public byte[] GetTextAlignment(ICommandEmitter e, AlignmentEnum alignment)
|
||||||
|
{
|
||||||
|
if (alignment == AlignmentEnum.Left)
|
||||||
|
return e.LeftAlign();
|
||||||
|
|
||||||
|
if (alignment == AlignmentEnum.Right)
|
||||||
|
return e.RightAlign();
|
||||||
|
|
||||||
|
return e.CenterAlign();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
117
PointOfSale/EpsonPrinterLinux/Services/PrintBody.cs
Normal file
117
PointOfSale/EpsonPrinterLinux/Services/PrintBody.cs
Normal file
@@ -0,0 +1,117 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using EpsonPrinter.Model;
|
||||||
|
using ESCPOS_NET.Emitters;
|
||||||
|
using Microsoft.Extensions.Configuration;
|
||||||
|
|
||||||
|
namespace EpsonPrinter.Services
|
||||||
|
{
|
||||||
|
public class PrintBody
|
||||||
|
{
|
||||||
|
private ICommandEmitter _e;
|
||||||
|
private IConfiguration _config;
|
||||||
|
|
||||||
|
private int productMaxWidth;
|
||||||
|
|
||||||
|
public PrintBody(ICommandEmitter e, IConfiguration config)
|
||||||
|
{
|
||||||
|
_e = e;
|
||||||
|
_config = config;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<byte[][]> Print(BodyModel model)
|
||||||
|
{
|
||||||
|
List<byte[][]> data = new List<byte[][]>();
|
||||||
|
|
||||||
|
byte[][] headerModel =
|
||||||
|
{
|
||||||
|
_e.SetStyles(PrintStyle.None),
|
||||||
|
_e.LeftAlign(),
|
||||||
|
_e.PrintLine($"Dato.........: {model.ReceiptTime}"),
|
||||||
|
_e.PrintLine($"Ekspedient...: {model.Staff}"),
|
||||||
|
_e.PrintLine($"Kvittering...: {model.ReceiptNumber}"),
|
||||||
|
_e.FeedLines(1)
|
||||||
|
};
|
||||||
|
data.Add(headerModel);
|
||||||
|
|
||||||
|
int printWidth = Convert.ToInt32(_config["PrintSettings:PrintWidth"]);
|
||||||
|
foreach (BodyProductModel product in model.Products)
|
||||||
|
{
|
||||||
|
//Size of product is max half of recipt
|
||||||
|
string totalProductLine = MakeProductNameString(product.Product, printWidth);
|
||||||
|
totalProductLine += MakeProductNumber(product.NoOfProduct, product.Price);
|
||||||
|
totalProductLine = MakeTotalProductPrice(totalProductLine, product.TotalPrice,printWidth);
|
||||||
|
|
||||||
|
byte[][] p =
|
||||||
|
{
|
||||||
|
_e.PrintLine(totalProductLine)
|
||||||
|
};
|
||||||
|
data.Add(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
PrintString printString = new PrintString();
|
||||||
|
string totalPricePrint = printString.MakePrintString(printWidth, $"Total: ", $"{model.TotalPrice:F} DKK");
|
||||||
|
byte[][] totalPrice =
|
||||||
|
{
|
||||||
|
_e.FeedLines(1),
|
||||||
|
_e.SetStyles(PrintStyle.Bold | PrintStyle.DoubleHeight),
|
||||||
|
_e.RightAlign(),
|
||||||
|
_e.PrintLine(totalPricePrint)
|
||||||
|
};
|
||||||
|
data.Add(totalPrice);
|
||||||
|
|
||||||
|
byte[][] vat =
|
||||||
|
{
|
||||||
|
_e.FeedLines(1),
|
||||||
|
_e.SetStyles(PrintStyle.None),
|
||||||
|
_e.LeftAlign(),
|
||||||
|
_e.PrintLine(MakeVat(printWidth,model.TotalVat))
|
||||||
|
};
|
||||||
|
data.Add(vat);
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
private string MakeProductNameString(string product, int totalWidth)
|
||||||
|
{
|
||||||
|
string productString = product;
|
||||||
|
productMaxWidth = (totalWidth / 2) - 5;
|
||||||
|
int productLength = product.Length;
|
||||||
|
if (productLength < productMaxWidth)
|
||||||
|
{
|
||||||
|
|
||||||
|
for (int i = productLength; i < productMaxWidth; i++)
|
||||||
|
{
|
||||||
|
productString += ".";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return productString;
|
||||||
|
}
|
||||||
|
|
||||||
|
private string MakeProductNumber(int noOfProduct, decimal price)
|
||||||
|
{
|
||||||
|
return $"{noOfProduct} á {price:F} DKK :";
|
||||||
|
}
|
||||||
|
|
||||||
|
private string MakeTotalProductPrice(string buffer, decimal totalPrice, int printWidth)
|
||||||
|
{
|
||||||
|
PrintString printString = new PrintString();
|
||||||
|
string p = $"{totalPrice:F} DKK";
|
||||||
|
string makePrintString = printString.MakePrintString(printWidth, buffer, p);
|
||||||
|
return makePrintString;
|
||||||
|
}
|
||||||
|
|
||||||
|
private string MakeVat(int printWidth, decimal vat)
|
||||||
|
{
|
||||||
|
PrintString printString = new PrintString();
|
||||||
|
string vatDesc = $"Moms udgør 25% :";
|
||||||
|
string v = $"{vat:F} DKK";
|
||||||
|
string vatString = printString.MakePrintString(printWidth, vatDesc, v);
|
||||||
|
return vatString;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
47
PointOfSale/EpsonPrinterLinux/Services/PrintFooter.cs
Normal file
47
PointOfSale/EpsonPrinterLinux/Services/PrintFooter.cs
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using EpsonPrinter.Model;
|
||||||
|
using ESCPOS_NET;
|
||||||
|
using ESCPOS_NET.Emitters;
|
||||||
|
|
||||||
|
namespace EpsonPrinter.Services
|
||||||
|
{
|
||||||
|
public class PrintFooter
|
||||||
|
{
|
||||||
|
private ICommandEmitter _e;
|
||||||
|
|
||||||
|
public PrintFooter(ICommandEmitter e)
|
||||||
|
{
|
||||||
|
_e = e;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<byte[][]> Print(List<FooterModel> model)
|
||||||
|
{
|
||||||
|
List<byte[][]> data = new List<byte[][]>();
|
||||||
|
PrintStyleCombination printStyleCombination = new PrintStyleCombination();
|
||||||
|
PrintAlignment printAlignment = new PrintAlignment();
|
||||||
|
byte[][] feedLines =
|
||||||
|
{
|
||||||
|
_e.FeedLines(1)
|
||||||
|
};
|
||||||
|
data.Add(feedLines);
|
||||||
|
foreach (FooterModel footerModel in model)
|
||||||
|
{
|
||||||
|
|
||||||
|
PrintStyle printStyle = printStyleCombination.Combine(footerModel.PrintStyles);
|
||||||
|
byte[][] bytes = {
|
||||||
|
_e.SetStyles(PrintStyle.None),
|
||||||
|
printAlignment.GetTextAlignment(_e,footerModel.TextAlignment),
|
||||||
|
_e.SetStyles(printStyle),
|
||||||
|
_e.PrintLine(footerModel.Value),
|
||||||
|
_e.FeedLines(footerModel.FeedingLines)
|
||||||
|
};
|
||||||
|
data.Add(bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
47
PointOfSale/EpsonPrinterLinux/Services/PrintHeader.cs
Normal file
47
PointOfSale/EpsonPrinterLinux/Services/PrintHeader.cs
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using EpsonPrinter.Model;
|
||||||
|
using ESCPOS_NET;
|
||||||
|
using ESCPOS_NET.Emitters;
|
||||||
|
using ESCPOS_NET.Utilities;
|
||||||
|
|
||||||
|
namespace EpsonPrinter.Services
|
||||||
|
{
|
||||||
|
public class PrintHeader
|
||||||
|
{
|
||||||
|
private ICommandEmitter _e;
|
||||||
|
|
||||||
|
public PrintHeader(ICommandEmitter e)
|
||||||
|
{
|
||||||
|
_e = e;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Byte[][]> Print(List<HeaderModel> model)
|
||||||
|
{
|
||||||
|
List<byte[][]> data = new List<byte[][]>();
|
||||||
|
PrintStyleCombination printStyleCombination = new PrintStyleCombination();
|
||||||
|
PrintAlignment printAlignment = new PrintAlignment();
|
||||||
|
foreach (HeaderModel headerModel in model)
|
||||||
|
{
|
||||||
|
|
||||||
|
PrintStyle printStyle = printStyleCombination.Combine(headerModel.PrintStyles);
|
||||||
|
byte[][] bytes = {
|
||||||
|
_e.SetStyles(PrintStyle.None),
|
||||||
|
printAlignment.GetTextAlignment(_e,headerModel.TextAlignment),
|
||||||
|
_e.SetStyles(printStyle),
|
||||||
|
_e.PrintLine(headerModel.Value),
|
||||||
|
_e.FeedLines(headerModel.FeedingLines)
|
||||||
|
};
|
||||||
|
data.Add(bytes);
|
||||||
|
}
|
||||||
|
byte[][] feedLines =
|
||||||
|
{
|
||||||
|
_e.FeedLines(1)
|
||||||
|
};
|
||||||
|
data.Add(feedLines);
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
44
PointOfSale/EpsonPrinterLinux/Services/PrintString.cs
Normal file
44
PointOfSale/EpsonPrinterLinux/Services/PrintString.cs
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace EpsonPrinter.Services
|
||||||
|
{
|
||||||
|
public class PrintString
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// An appropriate interval is converted into the length of
|
||||||
|
/// the tab about two texts. And make a printing data.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="iLineChars">
|
||||||
|
/// The width of the territory which it prints on is converted into the number of
|
||||||
|
/// characters, and that value is specified.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="strBuf">
|
||||||
|
/// It is necessary as an information for deciding the interval of the text.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="strPrice">
|
||||||
|
/// It is necessary as an information for deciding the interval of the text, too.
|
||||||
|
/// </param>
|
||||||
|
/// <returns>printing data.
|
||||||
|
/// </returns>
|
||||||
|
public String MakePrintString(int iLineChars, String strBuf, String strPrice)
|
||||||
|
{
|
||||||
|
int iSpaces = 0;
|
||||||
|
String tab = "";
|
||||||
|
try
|
||||||
|
{
|
||||||
|
iSpaces = iLineChars - (strBuf.Length + strPrice.Length);
|
||||||
|
for (int j = 0; j < iSpaces; j++)
|
||||||
|
{
|
||||||
|
tab += " ";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
return strBuf + tab + strPrice;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,69 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using EpsonPrinter.Enums;
|
||||||
|
using EpsonPrinter.Model;
|
||||||
|
using ESCPOS_NET.Emitters;
|
||||||
|
|
||||||
|
namespace EpsonPrinter.Services
|
||||||
|
{
|
||||||
|
public class PrintStyleCombination
|
||||||
|
{
|
||||||
|
public PrintStyle Combine(PrintStyleModel printStyleModel)
|
||||||
|
{
|
||||||
|
|
||||||
|
//Bold
|
||||||
|
if (printStyleModel.Bold && !printStyleModel.DoubleHeight && !printStyleModel.DoubleWidth && !printStyleModel.FontB && !printStyleModel.Underline)
|
||||||
|
return PrintStyle.Bold;
|
||||||
|
|
||||||
|
if (printStyleModel.Bold && printStyleModel.DoubleHeight && !printStyleModel.DoubleWidth && !printStyleModel.FontB && !printStyleModel.Underline)
|
||||||
|
return PrintStyle.Bold | PrintStyle.DoubleHeight;
|
||||||
|
|
||||||
|
if(printStyleModel.Bold && printStyleModel.DoubleHeight && printStyleModel.DoubleWidth && !printStyleModel.FontB && !printStyleModel.Underline)
|
||||||
|
return PrintStyle.Bold | PrintStyle.DoubleHeight | PrintStyle.DoubleWidth;
|
||||||
|
|
||||||
|
if (printStyleModel.Bold && printStyleModel.DoubleHeight && printStyleModel.DoubleWidth && printStyleModel.FontB && !printStyleModel.Underline)
|
||||||
|
return PrintStyle.Bold | PrintStyle.DoubleHeight | PrintStyle.DoubleWidth | PrintStyle.FontB;
|
||||||
|
|
||||||
|
if (printStyleModel.Bold && printStyleModel.DoubleHeight && printStyleModel.DoubleWidth && printStyleModel.FontB && printStyleModel.Underline)
|
||||||
|
return PrintStyle.Bold | PrintStyle.DoubleHeight | PrintStyle.DoubleWidth | PrintStyle.FontB | PrintStyle.Underline;
|
||||||
|
|
||||||
|
//DoubleHeight
|
||||||
|
if (printStyleModel.DoubleHeight && !printStyleModel.DoubleWidth && !printStyleModel.FontB && !printStyleModel.Underline)
|
||||||
|
return PrintStyle.DoubleHeight;
|
||||||
|
|
||||||
|
if (printStyleModel.DoubleHeight && printStyleModel.DoubleWidth && !printStyleModel.FontB && !printStyleModel.Underline)
|
||||||
|
return PrintStyle.DoubleHeight | PrintStyle.DoubleWidth;
|
||||||
|
|
||||||
|
if (printStyleModel.DoubleHeight && printStyleModel.DoubleWidth && printStyleModel.FontB && !printStyleModel.Underline)
|
||||||
|
return PrintStyle.DoubleHeight | PrintStyle.DoubleWidth | PrintStyle.FontB;
|
||||||
|
|
||||||
|
if (printStyleModel.DoubleHeight && printStyleModel.DoubleWidth && printStyleModel.FontB && printStyleModel.Underline)
|
||||||
|
return PrintStyle.DoubleHeight | PrintStyle.DoubleWidth | PrintStyle.FontB | PrintStyle.Underline;
|
||||||
|
|
||||||
|
//DoubleWidth
|
||||||
|
if (printStyleModel.DoubleWidth && !printStyleModel.FontB && !printStyleModel.Underline)
|
||||||
|
return PrintStyle.DoubleWidth;
|
||||||
|
|
||||||
|
if (printStyleModel.DoubleWidth && printStyleModel.FontB && !printStyleModel.Underline)
|
||||||
|
return PrintStyle.DoubleWidth | PrintStyle.FontB;
|
||||||
|
|
||||||
|
if (printStyleModel.DoubleWidth && printStyleModel.FontB && printStyleModel.Underline)
|
||||||
|
return PrintStyle.DoubleWidth | PrintStyle.FontB | PrintStyle.Underline;
|
||||||
|
|
||||||
|
//FontB
|
||||||
|
if (printStyleModel.FontB && !printStyleModel.Underline)
|
||||||
|
return PrintStyle.FontB;
|
||||||
|
|
||||||
|
if(printStyleModel.FontB && printStyleModel.Underline)
|
||||||
|
return PrintStyle.FontB | PrintStyle.Underline;
|
||||||
|
|
||||||
|
//Underline
|
||||||
|
if (printStyleModel.Underline)
|
||||||
|
return PrintStyle.Underline;
|
||||||
|
|
||||||
|
return PrintStyle.None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"Logging": {
|
||||||
|
"LogLevel": {
|
||||||
|
"Default": "Information",
|
||||||
|
"Microsoft": "Warning",
|
||||||
|
"Microsoft.Hosting.Lifetime": "Information"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
26
PointOfSale/EpsonPrinterLinux/appsettings.json
Normal file
26
PointOfSale/EpsonPrinterLinux/appsettings.json
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
{
|
||||||
|
"Logging": {
|
||||||
|
"LogLevel": {
|
||||||
|
"Default": "Information",
|
||||||
|
"Microsoft": "Warning",
|
||||||
|
"Microsoft.Hosting.Lifetime": "Information"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"AllowedHosts": "*",
|
||||||
|
"PrintSettings": {
|
||||||
|
"DevicePath": "/dev/usb/lp0",
|
||||||
|
"PrintWidth": 48,
|
||||||
|
"CodePage": "ISO8859_15_LATIN9",
|
||||||
|
"Defaults": {
|
||||||
|
"StoreName": "Blomster Til Alt",
|
||||||
|
"AddressLine1": "Adelgade 88",
|
||||||
|
"AddressLine2": "5400 Bogense",
|
||||||
|
"Cvr": "CVR: 37144436",
|
||||||
|
"Phone": "Tlf: 41 82 71 66",
|
||||||
|
"FooterLine1": "Tak for dit køb!",
|
||||||
|
"FooterLine2": "Vi håber du bliver glad for dine varer.",
|
||||||
|
"Staff": "Ukendt",
|
||||||
|
"ReceiptPrefix": "BON"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
73
PointOfSale/EpsonPrinterLinux/testdata.json
Normal file
73
PointOfSale/EpsonPrinterLinux/testdata.json
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
{
|
||||||
|
"logoBase64": "string",
|
||||||
|
"header": [
|
||||||
|
{
|
||||||
|
"value": "Første linie med ÆØÅ æøå",
|
||||||
|
"printStyles": {
|
||||||
|
"fontB": false,
|
||||||
|
"bold": true,
|
||||||
|
"doubleHeight": false,
|
||||||
|
"doubleWidth": false,
|
||||||
|
"underline": false
|
||||||
|
},
|
||||||
|
"textAlignment": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"value": "Anden linie",
|
||||||
|
"printStyles": {
|
||||||
|
"fontB": false,
|
||||||
|
"bold": true,
|
||||||
|
"doubleHeight": false,
|
||||||
|
"doubleWidth": false,
|
||||||
|
"underline": false
|
||||||
|
},
|
||||||
|
"textAlignment": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"value": "Tredje linie",
|
||||||
|
"printStyles": {
|
||||||
|
"fontB": false,
|
||||||
|
"bold": true,
|
||||||
|
"doubleHeight": false,
|
||||||
|
"doubleWidth": false,
|
||||||
|
"underline": false
|
||||||
|
},
|
||||||
|
"textAlignment": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"value": "Fjerde linie",
|
||||||
|
"printStyles": {
|
||||||
|
"fontB": false,
|
||||||
|
"bold": true,
|
||||||
|
"doubleHeight": false,
|
||||||
|
"doubleWidth": false,
|
||||||
|
"underline": false
|
||||||
|
},
|
||||||
|
"textAlignment": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"value": "Femte linie",
|
||||||
|
"printStyles": {
|
||||||
|
"fontB": false,
|
||||||
|
"bold": true,
|
||||||
|
"doubleHeight": false,
|
||||||
|
"doubleWidth": false,
|
||||||
|
"underline": false
|
||||||
|
},
|
||||||
|
"textAlignment": 0
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"footer": [
|
||||||
|
{
|
||||||
|
"value": "string",
|
||||||
|
"printStyles": {
|
||||||
|
"fontB": true,
|
||||||
|
"bold": true,
|
||||||
|
"doubleHeight": true,
|
||||||
|
"doubleWidth": true,
|
||||||
|
"underline": true
|
||||||
|
},
|
||||||
|
"textAlignment": 0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
7
PointOfSale/Pos.Api/Pos.Api.Database/Class1.cs
Normal file
7
PointOfSale/Pos.Api/Pos.Api.Database/Class1.cs
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
namespace Pos.Api.Database
|
||||||
|
{
|
||||||
|
public class Class1
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
162
PointOfSale/Pos.Api/Pos.Api.Database/Data/PosApiContext.cs
Normal file
162
PointOfSale/Pos.Api/Pos.Api.Database/Data/PosApiContext.cs
Normal file
@@ -0,0 +1,162 @@
|
|||||||
|
// <auto-generated> This file has been auto generated by EF Core Power Tools. </auto-generated>
|
||||||
|
#nullable disable
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Pos.Api.Database.Models;
|
||||||
|
|
||||||
|
namespace Pos.Api.Database.Data;
|
||||||
|
|
||||||
|
public partial class PosApiContext : DbContext
|
||||||
|
{
|
||||||
|
public PosApiContext(DbContextOptions<PosApiContext> options)
|
||||||
|
: base(options)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual DbSet<Employee> Employees { get; set; }
|
||||||
|
|
||||||
|
public virtual DbSet<LastUpdate> LastUpdates { get; set; }
|
||||||
|
|
||||||
|
public virtual DbSet<Payment> Payments { get; set; }
|
||||||
|
|
||||||
|
public virtual DbSet<Product> Products { get; set; }
|
||||||
|
|
||||||
|
public virtual DbSet<Productgroup> Productgroups { get; set; }
|
||||||
|
|
||||||
|
public virtual DbSet<Sale> Sales { get; set; }
|
||||||
|
|
||||||
|
public virtual DbSet<SaleLine> SaleLines { get; set; }
|
||||||
|
|
||||||
|
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
modelBuilder
|
||||||
|
.UseCollation("latin1_swedish_ci")
|
||||||
|
.HasCharSet("latin1");
|
||||||
|
|
||||||
|
modelBuilder.Entity<Employee>(entity =>
|
||||||
|
{
|
||||||
|
entity.HasKey(e => e.Id).HasName("PRIMARY");
|
||||||
|
|
||||||
|
entity
|
||||||
|
.ToTable("employee")
|
||||||
|
.HasCharSet("utf8mb4")
|
||||||
|
.UseCollation("utf8mb4_general_ci");
|
||||||
|
|
||||||
|
entity.Property(e => e.Id).HasColumnType("int(11)");
|
||||||
|
entity.Property(e => e.IsArchived).HasColumnType("tinyint(4)");
|
||||||
|
entity.Property(e => e.Name)
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(50);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity<LastUpdate>(entity =>
|
||||||
|
{
|
||||||
|
entity
|
||||||
|
.HasNoKey()
|
||||||
|
.ToTable("LastUpdate");
|
||||||
|
|
||||||
|
entity.Property(e => e.DateTime).HasColumnType("datetime");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity<Payment>(entity =>
|
||||||
|
{
|
||||||
|
entity.HasKey(e => e.Id).HasName("PRIMARY");
|
||||||
|
|
||||||
|
entity
|
||||||
|
.ToTable("payment")
|
||||||
|
.HasCharSet("armscii8")
|
||||||
|
.UseCollation("armscii8_bin");
|
||||||
|
|
||||||
|
entity.Property(e => e.Id).HasColumnType("int(11)");
|
||||||
|
entity.Property(e => e.Amount).HasPrecision(20, 6);
|
||||||
|
entity.Property(e => e.SaleId).HasColumnType("int(11)");
|
||||||
|
entity.Property(e => e.Type)
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("tinytext");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity<Product>(entity =>
|
||||||
|
{
|
||||||
|
entity.HasKey(e => e.Id).HasName("PRIMARY");
|
||||||
|
|
||||||
|
entity
|
||||||
|
.ToTable("product")
|
||||||
|
.HasCharSet("utf8mb4")
|
||||||
|
.UseCollation("utf8mb4_general_ci");
|
||||||
|
|
||||||
|
entity.HasIndex(e => e.ProductGroupId, "FK_Product_Categories");
|
||||||
|
|
||||||
|
entity.Property(e => e.Id)
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int(11)");
|
||||||
|
entity.Property(e => e.Description).HasColumnType("mediumtext");
|
||||||
|
entity.Property(e => e.Index).HasColumnType("int(11)");
|
||||||
|
entity.Property(e => e.IsArchived).HasColumnType("tinyint(4)");
|
||||||
|
entity.Property(e => e.Name)
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("tinytext");
|
||||||
|
entity.Property(e => e.Price).HasPrecision(10, 2);
|
||||||
|
entity.Property(e => e.ProductGroupId).HasColumnType("int(11)");
|
||||||
|
|
||||||
|
entity.HasOne(d => d.IdNavigation).WithOne(p => p.Product)
|
||||||
|
.HasForeignKey<Product>(d => d.Id)
|
||||||
|
.OnDelete(DeleteBehavior.ClientSetNull)
|
||||||
|
.HasConstraintName("FK_Product_ProductGroup");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity<Productgroup>(entity =>
|
||||||
|
{
|
||||||
|
entity.HasKey(e => e.Id).HasName("PRIMARY");
|
||||||
|
|
||||||
|
entity
|
||||||
|
.ToTable("productgroup")
|
||||||
|
.HasCharSet("utf8mb4")
|
||||||
|
.UseCollation("utf8mb4_general_ci");
|
||||||
|
|
||||||
|
entity.Property(e => e.Id).HasColumnType("int(11)");
|
||||||
|
entity.Property(e => e.Index).HasColumnType("int(11)");
|
||||||
|
entity.Property(e => e.IsArchived).HasColumnType("tinyint(4)");
|
||||||
|
entity.Property(e => e.Name)
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("tinytext");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity<Sale>(entity =>
|
||||||
|
{
|
||||||
|
entity.HasKey(e => e.Id).HasName("PRIMARY");
|
||||||
|
|
||||||
|
entity
|
||||||
|
.ToTable("sale")
|
||||||
|
.HasCharSet("armscii8")
|
||||||
|
.UseCollation("armscii8_bin");
|
||||||
|
|
||||||
|
entity.Property(e => e.Id).HasColumnType("int(11)");
|
||||||
|
entity.Property(e => e.EmployeeId).HasColumnType("int(11)");
|
||||||
|
entity.Property(e => e.Time).HasColumnType("datetime");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity<SaleLine>(entity =>
|
||||||
|
{
|
||||||
|
entity.HasKey(e => e.Id).HasName("PRIMARY");
|
||||||
|
|
||||||
|
entity
|
||||||
|
.ToTable("sale_line")
|
||||||
|
.HasCharSet("armscii8")
|
||||||
|
.UseCollation("armscii8_bin");
|
||||||
|
|
||||||
|
entity.Property(e => e.Id).HasColumnType("int(11)");
|
||||||
|
entity.Property(e => e.Pieces).HasColumnType("smallint(6)");
|
||||||
|
entity.Property(e => e.Price).HasPrecision(20, 6);
|
||||||
|
entity.Property(e => e.Product)
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("tinytext");
|
||||||
|
entity.Property(e => e.SaleId).HasColumnType("int(11)");
|
||||||
|
entity.Property(e => e.Total).HasPrecision(20, 6);
|
||||||
|
});
|
||||||
|
|
||||||
|
OnModelCreatingPartial(modelBuilder);
|
||||||
|
}
|
||||||
|
|
||||||
|
partial void OnModelCreatingPartial(ModelBuilder modelBuilder);
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.Extensions.Configuration;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Pos.Api.Database.Data
|
||||||
|
{
|
||||||
|
public partial class PosApiContext
|
||||||
|
{
|
||||||
|
|
||||||
|
protected override void OnConfiguring(
|
||||||
|
DbContextOptionsBuilder optionsBuilder)
|
||||||
|
{
|
||||||
|
LoadConfig l = new LoadConfig();
|
||||||
|
IConfiguration config = l.ByEnvironment();
|
||||||
|
string connectionString = config["MySQL"].ToString();
|
||||||
|
optionsBuilder
|
||||||
|
.UseMySql(connectionString, ServerVersion.AutoDetect(connectionString))
|
||||||
|
.UseLoggerFactory(LoggerFactory.Create(b => b
|
||||||
|
.AddFilter(level => level >= LogLevel.Information)))
|
||||||
|
.EnableSensitiveDataLogging()
|
||||||
|
.EnableDetailedErrors();
|
||||||
|
base.OnConfiguring(optionsBuilder);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
55
PointOfSale/Pos.Api/Pos.Api.Database/LoadConfig.cs
Normal file
55
PointOfSale/Pos.Api/Pos.Api.Database/LoadConfig.cs
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
using Microsoft.Extensions.Configuration;
|
||||||
|
|
||||||
|
namespace Pos.Api.Database
|
||||||
|
{
|
||||||
|
public class LoadConfig
|
||||||
|
{
|
||||||
|
private string dir;
|
||||||
|
public LoadConfig()
|
||||||
|
{
|
||||||
|
dir = AppDomain.CurrentDomain.BaseDirectory;
|
||||||
|
}
|
||||||
|
public IConfiguration ByEnvironment()
|
||||||
|
{
|
||||||
|
//Console.Out.WriteLine($"Json path: {dir}");
|
||||||
|
#if DEBUG
|
||||||
|
|
||||||
|
var config = new ConfigurationBuilder()
|
||||||
|
.SetBasePath(dir)
|
||||||
|
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
|
||||||
|
.AddJsonFile("appsettings.Development.json", optional: true, reloadOnChange: true)
|
||||||
|
.Build();
|
||||||
|
return config;
|
||||||
|
|
||||||
|
#else
|
||||||
|
var config = new ConfigurationBuilder()
|
||||||
|
.SetBasePath(dir)
|
||||||
|
.AddJsonFile("appsettings.Production.json", optional: true, reloadOnChange: true)
|
||||||
|
.Build();
|
||||||
|
return config;
|
||||||
|
#endif
|
||||||
|
//Running in a environment that not is supported in this setup
|
||||||
|
throw new Exception("HostingEnvironment is not supported! This config setup only supports Development or Production");
|
||||||
|
}
|
||||||
|
|
||||||
|
public IConfiguration DebugConfiguration()
|
||||||
|
{
|
||||||
|
var config = new ConfigurationBuilder()
|
||||||
|
.SetBasePath(dir)
|
||||||
|
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
|
||||||
|
.AddJsonFile("appsettings.Development.json", optional: true, reloadOnChange: true)
|
||||||
|
.Build();
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IConfiguration ReleaseConfiguration()
|
||||||
|
{
|
||||||
|
var config = new ConfigurationBuilder()
|
||||||
|
.SetBasePath(dir)
|
||||||
|
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
|
||||||
|
.AddJsonFile("appsettings.Production.json", optional: true, reloadOnChange: true)
|
||||||
|
.Build();
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
15
PointOfSale/Pos.Api/Pos.Api.Database/Models/Employee.cs
Normal file
15
PointOfSale/Pos.Api/Pos.Api.Database/Models/Employee.cs
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
// <auto-generated> This file has been auto generated by EF Core Power Tools. </auto-generated>
|
||||||
|
#nullable disable
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Pos.Api.Database.Models;
|
||||||
|
|
||||||
|
public partial class Employee
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
|
||||||
|
public string Name { get; set; }
|
||||||
|
|
||||||
|
public sbyte IsArchived { get; set; }
|
||||||
|
}
|
||||||
11
PointOfSale/Pos.Api/Pos.Api.Database/Models/LastUpdate.cs
Normal file
11
PointOfSale/Pos.Api/Pos.Api.Database/Models/LastUpdate.cs
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
// <auto-generated> This file has been auto generated by EF Core Power Tools. </auto-generated>
|
||||||
|
#nullable disable
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Pos.Api.Database.Models;
|
||||||
|
|
||||||
|
public partial class LastUpdate
|
||||||
|
{
|
||||||
|
public DateTime? DateTime { get; set; }
|
||||||
|
}
|
||||||
17
PointOfSale/Pos.Api/Pos.Api.Database/Models/Payment.cs
Normal file
17
PointOfSale/Pos.Api/Pos.Api.Database/Models/Payment.cs
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
// <auto-generated> This file has been auto generated by EF Core Power Tools. </auto-generated>
|
||||||
|
#nullable disable
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Pos.Api.Database.Models;
|
||||||
|
|
||||||
|
public partial class Payment
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
|
||||||
|
public int SaleId { get; set; }
|
||||||
|
|
||||||
|
public decimal Amount { get; set; }
|
||||||
|
|
||||||
|
public string Type { get; set; }
|
||||||
|
}
|
||||||
25
PointOfSale/Pos.Api/Pos.Api.Database/Models/Product.cs
Normal file
25
PointOfSale/Pos.Api/Pos.Api.Database/Models/Product.cs
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
// <auto-generated> This file has been auto generated by EF Core Power Tools. </auto-generated>
|
||||||
|
#nullable disable
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Pos.Api.Database.Models;
|
||||||
|
|
||||||
|
public partial class Product
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
|
||||||
|
public string Name { get; set; }
|
||||||
|
|
||||||
|
public decimal Price { get; set; }
|
||||||
|
|
||||||
|
public string Description { get; set; }
|
||||||
|
|
||||||
|
public int ProductGroupId { get; set; }
|
||||||
|
|
||||||
|
public sbyte IsArchived { get; set; }
|
||||||
|
|
||||||
|
public int Index { get; set; }
|
||||||
|
|
||||||
|
public virtual Productgroup IdNavigation { get; set; }
|
||||||
|
}
|
||||||
19
PointOfSale/Pos.Api/Pos.Api.Database/Models/Productgroup.cs
Normal file
19
PointOfSale/Pos.Api/Pos.Api.Database/Models/Productgroup.cs
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
// <auto-generated> This file has been auto generated by EF Core Power Tools. </auto-generated>
|
||||||
|
#nullable disable
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Pos.Api.Database.Models;
|
||||||
|
|
||||||
|
public partial class Productgroup
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
|
||||||
|
public string Name { get; set; }
|
||||||
|
|
||||||
|
public sbyte IsArchived { get; set; }
|
||||||
|
|
||||||
|
public int Index { get; set; }
|
||||||
|
|
||||||
|
public virtual Product Product { get; set; }
|
||||||
|
}
|
||||||
15
PointOfSale/Pos.Api/Pos.Api.Database/Models/Sale.cs
Normal file
15
PointOfSale/Pos.Api/Pos.Api.Database/Models/Sale.cs
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
// <auto-generated> This file has been auto generated by EF Core Power Tools. </auto-generated>
|
||||||
|
#nullable disable
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Pos.Api.Database.Models;
|
||||||
|
|
||||||
|
public partial class Sale
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
|
||||||
|
public DateTime Time { get; set; }
|
||||||
|
|
||||||
|
public int EmployeeId { get; set; }
|
||||||
|
}
|
||||||
21
PointOfSale/Pos.Api/Pos.Api.Database/Models/SaleLine.cs
Normal file
21
PointOfSale/Pos.Api/Pos.Api.Database/Models/SaleLine.cs
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
// <auto-generated> This file has been auto generated by EF Core Power Tools. </auto-generated>
|
||||||
|
#nullable disable
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Pos.Api.Database.Models;
|
||||||
|
|
||||||
|
public partial class SaleLine
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
|
||||||
|
public int SaleId { get; set; }
|
||||||
|
|
||||||
|
public string Product { get; set; }
|
||||||
|
|
||||||
|
public short Pieces { get; set; }
|
||||||
|
|
||||||
|
public decimal Price { get; set; }
|
||||||
|
|
||||||
|
public decimal Total { get; set; }
|
||||||
|
}
|
||||||
15
PointOfSale/Pos.Api/Pos.Api.Database/Pos.Api.Database.csproj
Normal file
15
PointOfSale/Pos.Api/Pos.Api.Database/Pos.Api.Database.csproj
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net7.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Configuration" Version="7.0.0" />
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="7.0.0" />
|
||||||
|
<PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="7.0.0" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
66
PointOfSale/Pos.Api/Pos.Api.Database/efpt.config.json
Normal file
66
PointOfSale/Pos.Api/Pos.Api.Database/efpt.config.json
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
{
|
||||||
|
"CodeGenerationMode": 3,
|
||||||
|
"ContextClassName": "PosApiContext",
|
||||||
|
"ContextNamespace": null,
|
||||||
|
"DefaultDacpacSchema": null,
|
||||||
|
"FilterSchemas": false,
|
||||||
|
"IncludeConnectionString": false,
|
||||||
|
"ModelNamespace": null,
|
||||||
|
"OutputContextPath": "Data",
|
||||||
|
"OutputPath": "Models",
|
||||||
|
"PreserveCasingWithRegex": true,
|
||||||
|
"ProjectRootNamespace": "Pos.Api.Database",
|
||||||
|
"Schemas": null,
|
||||||
|
"SelectedHandlebarsLanguage": 0,
|
||||||
|
"SelectedToBeGenerated": 0,
|
||||||
|
"Tables": [
|
||||||
|
{
|
||||||
|
"Name": "employee",
|
||||||
|
"ObjectType": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Name": "LastUpdate",
|
||||||
|
"ObjectType": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Name": "payment",
|
||||||
|
"ObjectType": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Name": "product",
|
||||||
|
"ObjectType": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Name": "productgroup",
|
||||||
|
"ObjectType": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Name": "sale",
|
||||||
|
"ObjectType": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Name": "sale_line",
|
||||||
|
"ObjectType": 0
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"UiHint": "simply.com",
|
||||||
|
"UncountableWords": null,
|
||||||
|
"UseBoolPropertiesWithoutDefaultSql": false,
|
||||||
|
"UseDatabaseNames": false,
|
||||||
|
"UseDateOnlyTimeOnly": false,
|
||||||
|
"UseDbContextSplitting": false,
|
||||||
|
"UseFluentApiOnly": true,
|
||||||
|
"UseHandleBars": false,
|
||||||
|
"UseHierarchyId": false,
|
||||||
|
"UseInflector": true,
|
||||||
|
"UseLegacyPluralizer": false,
|
||||||
|
"UseManyToManyEntity": false,
|
||||||
|
"UseNoDefaultConstructor": false,
|
||||||
|
"UseNoObjectFilter": false,
|
||||||
|
"UseNodaTime": false,
|
||||||
|
"UseNullableReferences": false,
|
||||||
|
"UseSchemaFolders": false,
|
||||||
|
"UseSchemaNamespaces": false,
|
||||||
|
"UseSpatial": false,
|
||||||
|
"UseT4": false
|
||||||
|
}
|
||||||
29
PointOfSale/Pos.Api/Pos.Api/BaseController.cs
Normal file
29
PointOfSale/Pos.Api/Pos.Api/BaseController.cs
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.AspNetCore.Mvc.Filters;
|
||||||
|
using Pos.Api.Database;
|
||||||
|
|
||||||
|
namespace Pos.Api
|
||||||
|
{
|
||||||
|
public class BaseController : Controller
|
||||||
|
{
|
||||||
|
private readonly IConfiguration _config;
|
||||||
|
public BaseController(IConfiguration config)
|
||||||
|
{
|
||||||
|
_config = config;
|
||||||
|
}
|
||||||
|
public override async Task OnActionExecutionAsync(ActionExecutingContext context,
|
||||||
|
ActionExecutionDelegate next)
|
||||||
|
{
|
||||||
|
HttpRequest request = Request;
|
||||||
|
string apiKey = request.Headers["ApiKey"].ToString();
|
||||||
|
string? apiKeyRequest = _config["ApiKey"];
|
||||||
|
if (apiKeyRequest == null)
|
||||||
|
{
|
||||||
|
throw new NullReferenceException("ApiKey header is missing");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!apiKeyRequest.Equals(apiKey))
|
||||||
|
throw new ArgumentException("ApiKey is wrong");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
151
PointOfSale/Pos.Api/Pos.Api/Controllers/PosController.cs
Normal file
151
PointOfSale/Pos.Api/Pos.Api/Controllers/PosController.cs
Normal file
@@ -0,0 +1,151 @@
|
|||||||
|
using System.Diagnostics.Eventing.Reader;
|
||||||
|
using System.Net;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.Extensions.Primitives;
|
||||||
|
using Pos.Api.Database.Data;
|
||||||
|
using Pos.Api.Database.Models;
|
||||||
|
|
||||||
|
namespace Pos.Api.Controllers
|
||||||
|
{
|
||||||
|
[Route("api/[controller]")]
|
||||||
|
[ApiController]
|
||||||
|
public class PosController : Controller
|
||||||
|
{
|
||||||
|
private readonly PosApiContext _context;
|
||||||
|
private readonly IConfiguration _config;
|
||||||
|
|
||||||
|
public PosController(IConfiguration config, PosApiContext context)
|
||||||
|
{
|
||||||
|
_context = context;
|
||||||
|
_config = config;
|
||||||
|
}
|
||||||
|
|
||||||
|
//[HttpGet("/update")]
|
||||||
|
//public DateTime LastUpdate()
|
||||||
|
//{
|
||||||
|
|
||||||
|
// LastUpdate? lastUpdate = _context.LastUpdates.SingleOrDefault();
|
||||||
|
// if (lastUpdate == null)
|
||||||
|
// {
|
||||||
|
// return DateTime.Now;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// DateTime last = lastUpdate.DateTime.Value;
|
||||||
|
// lastUpdate.DateTime = DateTime.Now;
|
||||||
|
// _context.SaveChanges();
|
||||||
|
|
||||||
|
// return last;
|
||||||
|
//}
|
||||||
|
|
||||||
|
[HttpPost("/employee")]
|
||||||
|
public void Employee(Employee employee)
|
||||||
|
{
|
||||||
|
ValidateApiKey();
|
||||||
|
|
||||||
|
Employee? dbEmployee = _context.Employees.SingleOrDefault(c => c.Id == employee.Id);
|
||||||
|
if (dbEmployee == null)
|
||||||
|
{
|
||||||
|
dbEmployee = new Employee();
|
||||||
|
dbEmployee.Id = employee.Id;
|
||||||
|
dbEmployee.IsArchived = employee.IsArchived;
|
||||||
|
_context.Employees.Add(dbEmployee);
|
||||||
|
}
|
||||||
|
dbEmployee.Name = employee.Name;
|
||||||
|
|
||||||
|
_context.SaveChanges();
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPost("/productgroup")]
|
||||||
|
public void Product(Productgroup productGroup)
|
||||||
|
{
|
||||||
|
ValidateApiKey();
|
||||||
|
|
||||||
|
Productgroup dbProductGroup = _context.Productgroups.SingleOrDefault(c => c.Id == productGroup.Id);
|
||||||
|
if (dbProductGroup == null)
|
||||||
|
{
|
||||||
|
dbProductGroup = new Productgroup();
|
||||||
|
dbProductGroup.Id = productGroup.Id;
|
||||||
|
_context.Productgroups.Add(dbProductGroup);
|
||||||
|
}
|
||||||
|
dbProductGroup.IsArchived = productGroup.IsArchived;
|
||||||
|
dbProductGroup.Name = productGroup.Name;
|
||||||
|
dbProductGroup.Index = productGroup.Index;
|
||||||
|
_context.SaveChanges();
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPost("/sale")]
|
||||||
|
public void Sale(Sale sale)
|
||||||
|
{
|
||||||
|
ValidateApiKey();
|
||||||
|
|
||||||
|
Sale? dbSale = _context.Sales.SingleOrDefault(c => c.Id == sale.Id);
|
||||||
|
if (dbSale == null)
|
||||||
|
{
|
||||||
|
dbSale = new Sale();
|
||||||
|
dbSale.Id = sale.Id;
|
||||||
|
_context.Sales.Add(dbSale);
|
||||||
|
}
|
||||||
|
dbSale.EmployeeId = sale.EmployeeId;
|
||||||
|
dbSale.Time = sale.Time;
|
||||||
|
_context.SaveChanges();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPost("/saleline")]
|
||||||
|
public void SaleLine(SaleLine saleLine)
|
||||||
|
{
|
||||||
|
ValidateApiKey();
|
||||||
|
|
||||||
|
SaleLine? dbSaleLine = _context.SaleLines.SingleOrDefault(c => c.Id == saleLine.Id);
|
||||||
|
if (dbSaleLine == null)
|
||||||
|
{
|
||||||
|
dbSaleLine = new SaleLine();
|
||||||
|
dbSaleLine.Id = saleLine.Id;
|
||||||
|
_context.SaleLines.Add(dbSaleLine);
|
||||||
|
}
|
||||||
|
dbSaleLine.SaleId = saleLine.SaleId;
|
||||||
|
dbSaleLine.Price = saleLine.Price;
|
||||||
|
dbSaleLine.Pieces = saleLine.Pieces;
|
||||||
|
dbSaleLine.Price = saleLine.Price;
|
||||||
|
dbSaleLine.Product = saleLine.Product;
|
||||||
|
dbSaleLine.Total = saleLine.Total;
|
||||||
|
_context.SaveChanges();
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPost("/payment")]
|
||||||
|
public void Payment(Payment payment)
|
||||||
|
{
|
||||||
|
ValidateApiKey();
|
||||||
|
|
||||||
|
Payment? dbPayment = _context.Payments.SingleOrDefault(c => c.Id == payment.Id);
|
||||||
|
if (dbPayment == null)
|
||||||
|
{
|
||||||
|
dbPayment = new Payment();
|
||||||
|
dbPayment.Id = payment.Id;
|
||||||
|
_context.Payments.Add(dbPayment);
|
||||||
|
}
|
||||||
|
dbPayment.Amount = payment.Amount;
|
||||||
|
dbPayment.SaleId = payment.SaleId;
|
||||||
|
dbPayment.Type = payment.Type;
|
||||||
|
_context.SaveChanges();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ValidateApiKey()
|
||||||
|
{
|
||||||
|
IHeaderDictionary headers = Request.Headers;
|
||||||
|
if (!headers.ContainsKey("ApiKey"))
|
||||||
|
{
|
||||||
|
throw new MissingFieldException("ApiKey missing");
|
||||||
|
}
|
||||||
|
|
||||||
|
StringValues apiKeyHeader = headers["ApiKey"];
|
||||||
|
string? apiKey = _config["ApiKey"];
|
||||||
|
if (!apiKeyHeader.Equals(apiKey))
|
||||||
|
{
|
||||||
|
throw new MissingFieldException("ApiKey is wrong");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
|
||||||
|
namespace Pos.Api.Controllers
|
||||||
|
{
|
||||||
|
[ApiController]
|
||||||
|
[Route("[controller]")]
|
||||||
|
public class WeatherForecastController : ControllerBase
|
||||||
|
{
|
||||||
|
private static readonly string[] Summaries = new[]
|
||||||
|
{
|
||||||
|
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
|
||||||
|
};
|
||||||
|
|
||||||
|
private readonly ILogger<WeatherForecastController> _logger;
|
||||||
|
|
||||||
|
public WeatherForecastController(ILogger<WeatherForecastController> logger)
|
||||||
|
{
|
||||||
|
_logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpGet(Name = "GetWeatherForecast")]
|
||||||
|
public IEnumerable<WeatherForecast> Get()
|
||||||
|
{
|
||||||
|
return Enumerable.Range(1, 5).Select(index => new WeatherForecast
|
||||||
|
{
|
||||||
|
Date = DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
|
||||||
|
TemperatureC = Random.Shared.Next(-20, 55),
|
||||||
|
Summary = Summaries[Random.Shared.Next(Summaries.Length)]
|
||||||
|
})
|
||||||
|
.ToArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
using Microsoft.OpenApi.Any;
|
||||||
|
using Microsoft.OpenApi.Models;
|
||||||
|
using Pos.Api.Database;
|
||||||
|
using Swashbuckle.AspNetCore.SwaggerGen;
|
||||||
|
|
||||||
|
namespace Pos.Api.Helper
|
||||||
|
{
|
||||||
|
public class ApiKeyHeaderOperationFilter : IOperationFilter
|
||||||
|
{
|
||||||
|
private readonly IConfiguration _config;
|
||||||
|
|
||||||
|
public ApiKeyHeaderOperationFilter(IConfiguration config)
|
||||||
|
{
|
||||||
|
_config = config;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Apply(OpenApiOperation operation, OperationFilterContext context)
|
||||||
|
{
|
||||||
|
string? apiKey = _config["ApiKey"];
|
||||||
|
operation.Parameters.Add(new OpenApiParameter
|
||||||
|
{
|
||||||
|
Name = "ApiKey",
|
||||||
|
In = ParameterLocation.Header,
|
||||||
|
Required = true,
|
||||||
|
Schema = new OpenApiSchema
|
||||||
|
{
|
||||||
|
Type = "string",
|
||||||
|
Default = new OpenApiString(apiKey)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
55
PointOfSale/Pos.Api/Pos.Api/Helper/LoadConfig.cs
Normal file
55
PointOfSale/Pos.Api/Pos.Api/Helper/LoadConfig.cs
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
using Microsoft.Extensions.Configuration;
|
||||||
|
|
||||||
|
namespace Pos.Api.Helper
|
||||||
|
{
|
||||||
|
public class LoadConfig
|
||||||
|
{
|
||||||
|
private string dir;
|
||||||
|
public LoadConfig()
|
||||||
|
{
|
||||||
|
dir = AppDomain.CurrentDomain.BaseDirectory;
|
||||||
|
}
|
||||||
|
public IConfiguration ByEnvironment()
|
||||||
|
{
|
||||||
|
//Console.Out.WriteLine($"Json path: {dir}");
|
||||||
|
#if DEBUG
|
||||||
|
|
||||||
|
var config = new ConfigurationBuilder()
|
||||||
|
.SetBasePath(dir)
|
||||||
|
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
|
||||||
|
.AddJsonFile("appsettings.Development.json", optional: true, reloadOnChange: true)
|
||||||
|
.Build();
|
||||||
|
return config;
|
||||||
|
|
||||||
|
#else
|
||||||
|
var config = new ConfigurationBuilder()
|
||||||
|
.SetBasePath(dir)
|
||||||
|
.AddJsonFile("appsettings.Production.json", optional: true, reloadOnChange: true)
|
||||||
|
.Build();
|
||||||
|
return config;
|
||||||
|
#endif
|
||||||
|
//Running in a environment that not is supported in this setup
|
||||||
|
throw new Exception("HostingEnvironment is not supported! This config setup only supports Development or Production");
|
||||||
|
}
|
||||||
|
|
||||||
|
public IConfiguration DebugConfiguration()
|
||||||
|
{
|
||||||
|
var config = new ConfigurationBuilder()
|
||||||
|
.SetBasePath(dir)
|
||||||
|
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
|
||||||
|
.AddJsonFile("appsettings.Development.json", optional: true, reloadOnChange: true)
|
||||||
|
.Build();
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IConfiguration ReleaseConfiguration()
|
||||||
|
{
|
||||||
|
var config = new ConfigurationBuilder()
|
||||||
|
.SetBasePath(dir)
|
||||||
|
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
|
||||||
|
.AddJsonFile("appsettings.Production.json", optional: true, reloadOnChange: true)
|
||||||
|
.Build();
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
24
PointOfSale/Pos.Api/Pos.Api/Pos.Api.csproj
Normal file
24
PointOfSale/Pos.Api/Pos.Api/Pos.Api.csproj
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net7.0</TargetFramework>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="7.0.7" />
|
||||||
|
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\Pos.Api.Database\Pos.Api.Database.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Content Update="appsettings.json">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
</Content>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
32
PointOfSale/Pos.Api/Pos.Api/Program.cs
Normal file
32
PointOfSale/Pos.Api/Pos.Api/Program.cs
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
using Pos.Api.Database;
|
||||||
|
using Pos.Api.Database.Data;
|
||||||
|
using Pos.Api.Helper;
|
||||||
|
using LoadConfig = Pos.Api.Helper.LoadConfig;
|
||||||
|
|
||||||
|
var builder = WebApplication.CreateBuilder(args);
|
||||||
|
|
||||||
|
// Add services to the container.
|
||||||
|
LoadConfig loadConfig = new LoadConfig();
|
||||||
|
IConfiguration config = loadConfig.ByEnvironment();
|
||||||
|
builder.Services.AddSingleton(config);
|
||||||
|
builder.Services.AddControllers();
|
||||||
|
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
|
||||||
|
builder.Services.AddEndpointsApiExplorer();
|
||||||
|
builder.Services.AddSwaggerGen(c =>
|
||||||
|
c.OperationFilter<ApiKeyHeaderOperationFilter>()
|
||||||
|
);
|
||||||
|
builder.Services.AddDbContext<PosApiContext>();
|
||||||
|
var app = builder.Build();
|
||||||
|
|
||||||
|
// Configure the HTTP request pipeline.
|
||||||
|
if (app.Environment.IsDevelopment())
|
||||||
|
{
|
||||||
|
app.UseSwagger();
|
||||||
|
app.UseSwaggerUI();
|
||||||
|
}
|
||||||
|
|
||||||
|
app.UseAuthorization();
|
||||||
|
|
||||||
|
app.MapControllers();
|
||||||
|
|
||||||
|
app.Run();
|
||||||
31
PointOfSale/Pos.Api/Pos.Api/Properties/launchSettings.json
Normal file
31
PointOfSale/Pos.Api/Pos.Api/Properties/launchSettings.json
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
{
|
||||||
|
"$schema": "https://json.schemastore.org/launchsettings.json",
|
||||||
|
"iisSettings": {
|
||||||
|
"windowsAuthentication": false,
|
||||||
|
"anonymousAuthentication": true,
|
||||||
|
"iisExpress": {
|
||||||
|
"applicationUrl": "http://localhost:53151",
|
||||||
|
"sslPort": 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"profiles": {
|
||||||
|
"http": {
|
||||||
|
"commandName": "Project",
|
||||||
|
"dotnetRunMessages": true,
|
||||||
|
"launchBrowser": true,
|
||||||
|
"launchUrl": "swagger",
|
||||||
|
"applicationUrl": "http://localhost:5297",
|
||||||
|
"environmentVariables": {
|
||||||
|
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"IIS Express": {
|
||||||
|
"commandName": "IISExpress",
|
||||||
|
"launchBrowser": true,
|
||||||
|
"launchUrl": "swagger",
|
||||||
|
"environmentVariables": {
|
||||||
|
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
13
PointOfSale/Pos.Api/Pos.Api/WeatherForecast.cs
Normal file
13
PointOfSale/Pos.Api/Pos.Api/WeatherForecast.cs
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
namespace Pos.Api
|
||||||
|
{
|
||||||
|
public class WeatherForecast
|
||||||
|
{
|
||||||
|
public DateOnly Date { get; set; }
|
||||||
|
|
||||||
|
public int TemperatureC { get; set; }
|
||||||
|
|
||||||
|
public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
|
||||||
|
|
||||||
|
public string? Summary { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
8
PointOfSale/Pos.Api/Pos.Api/appsettings.Development.json
Normal file
8
PointOfSale/Pos.Api/Pos.Api/appsettings.Development.json
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"Logging": {
|
||||||
|
"LogLevel": {
|
||||||
|
"Default": "Information",
|
||||||
|
"Microsoft.AspNetCore": "Warning"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
11
PointOfSale/Pos.Api/Pos.Api/appsettings.json
Normal file
11
PointOfSale/Pos.Api/Pos.Api/appsettings.json
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"Logging": {
|
||||||
|
"LogLevel": {
|
||||||
|
"Default": "Information",
|
||||||
|
"Microsoft.AspNetCore": "Warning"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"AllowedHosts": "*",
|
||||||
|
"MySQL": "Data Source=mysql22.unoeuro.com;Initial Catalog=blomstertilalt_dk_db;Persist Security Info=False;User ID=blomstertil_dk;Password=amccpy6l",
|
||||||
|
"ApiKey": "ad0YfMYm5bdVGjmXkJBOdNggQaWtkB9nzyQv68GAcB7mpf9onGBP9j3DJ46S7go30NwaQgoZBNS7hZDOM79KTyU3K2ysMW2x4mWGHOkETJmWadaMXBTGpoWn0ef9KiUN"
|
||||||
|
}
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
using Microsoft.Extensions.Configuration;
|
||||||
|
|
||||||
|
namespace Pos.Dispatcher.Database
|
||||||
|
{
|
||||||
|
public class LoadConfig
|
||||||
|
{
|
||||||
|
private string dir;
|
||||||
|
public LoadConfig()
|
||||||
|
{
|
||||||
|
dir = AppDomain.CurrentDomain.BaseDirectory;
|
||||||
|
}
|
||||||
|
public IConfiguration ByEnvironment()
|
||||||
|
{
|
||||||
|
//Console.Out.WriteLine($"Json path: {dir}");
|
||||||
|
#if DEBUG
|
||||||
|
|
||||||
|
var config = new ConfigurationBuilder()
|
||||||
|
.SetBasePath(dir)
|
||||||
|
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
|
||||||
|
.AddJsonFile("appsettings.Development.json", optional: true, reloadOnChange: true)
|
||||||
|
.Build();
|
||||||
|
return config;
|
||||||
|
|
||||||
|
#else
|
||||||
|
var config = new ConfigurationBuilder()
|
||||||
|
.SetBasePath(dir)
|
||||||
|
.AddJsonFile("appsettings.Production.json", optional: true, reloadOnChange: true)
|
||||||
|
.Build();
|
||||||
|
return config;
|
||||||
|
#endif
|
||||||
|
//Running in a environment that not is supported in this setup
|
||||||
|
throw new Exception("HostingEnvironment is not supported! This config setup only supports Development or Production");
|
||||||
|
}
|
||||||
|
|
||||||
|
public IConfiguration DebugConfiguration()
|
||||||
|
{
|
||||||
|
var config = new ConfigurationBuilder()
|
||||||
|
.SetBasePath(dir)
|
||||||
|
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
|
||||||
|
.AddJsonFile("appsettings.Development.json", optional: true, reloadOnChange: true)
|
||||||
|
.Build();
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IConfiguration ReleaseConfiguration()
|
||||||
|
{
|
||||||
|
var config = new ConfigurationBuilder()
|
||||||
|
.SetBasePath(dir)
|
||||||
|
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
|
||||||
|
.AddJsonFile("appsettings.Production.json", optional: true, reloadOnChange: true)
|
||||||
|
.Build();
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,75 @@
|
|||||||
|
// <auto-generated> This file has been auto generated by EF Core Power Tools. </auto-generated>
|
||||||
|
#nullable disable
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Pos.Dispatcher.Database.Models;
|
||||||
|
|
||||||
|
namespace Pos.Dispatcher.Database.Model;
|
||||||
|
|
||||||
|
public partial class PosDispatcherContext : DbContext
|
||||||
|
{
|
||||||
|
public PosDispatcherContext(DbContextOptions<PosDispatcherContext> options)
|
||||||
|
: base(options)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual DbSet<Employee> Employees { get; set; }
|
||||||
|
|
||||||
|
public virtual DbSet<Payment> Payments { get; set; }
|
||||||
|
|
||||||
|
public virtual DbSet<Product> Products { get; set; }
|
||||||
|
|
||||||
|
public virtual DbSet<Productgroup> Productgroups { get; set; }
|
||||||
|
|
||||||
|
public virtual DbSet<Sale> Sales { get; set; }
|
||||||
|
|
||||||
|
public virtual DbSet<SaleLine> SaleLines { get; set; }
|
||||||
|
|
||||||
|
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
modelBuilder
|
||||||
|
.UseCollation("armscii8_bin")
|
||||||
|
.HasCharSet("armscii8");
|
||||||
|
|
||||||
|
modelBuilder.Entity<Employee>(entity =>
|
||||||
|
{
|
||||||
|
entity.HasKey(e => e.Id).HasName("PRIMARY");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity<Payment>(entity =>
|
||||||
|
{
|
||||||
|
entity.HasKey(e => e.Id).HasName("PRIMARY");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity<Product>(entity =>
|
||||||
|
{
|
||||||
|
entity.HasKey(e => e.Id).HasName("PRIMARY");
|
||||||
|
|
||||||
|
entity.Property(e => e.Id).ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
entity.HasOne(d => d.IdNavigation).WithOne(p => p.Product)
|
||||||
|
.OnDelete(DeleteBehavior.ClientSetNull)
|
||||||
|
.HasConstraintName("FK_Product_ProductGroup");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity<Productgroup>(entity =>
|
||||||
|
{
|
||||||
|
entity.HasKey(e => e.Id).HasName("PRIMARY");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity<Sale>(entity =>
|
||||||
|
{
|
||||||
|
entity.HasKey(e => e.Id).HasName("PRIMARY");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity<SaleLine>(entity =>
|
||||||
|
{
|
||||||
|
entity.HasKey(e => e.Id).HasName("PRIMARY");
|
||||||
|
});
|
||||||
|
|
||||||
|
OnModelCreatingPartial(modelBuilder);
|
||||||
|
}
|
||||||
|
|
||||||
|
partial void OnModelCreatingPartial(ModelBuilder modelBuilder);
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.Extensions.Configuration;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
|
namespace Pos.Dispatcher.Database.Model
|
||||||
|
{
|
||||||
|
public partial class PosDispatcherContext
|
||||||
|
{
|
||||||
|
protected override void OnConfiguring(
|
||||||
|
DbContextOptionsBuilder optionsBuilder)
|
||||||
|
{
|
||||||
|
LoadConfig l = new LoadConfig();
|
||||||
|
IConfiguration config = l.ByEnvironment();
|
||||||
|
string connectionString = config["MariaSqlServer"].ToString();
|
||||||
|
optionsBuilder
|
||||||
|
.UseMySql(connectionString, ServerVersion.AutoDetect(connectionString))
|
||||||
|
.UseLoggerFactory(LoggerFactory.Create(b => b
|
||||||
|
.AddFilter(level => level >= LogLevel.Information)))
|
||||||
|
.EnableSensitiveDataLogging()
|
||||||
|
.EnableDetailedErrors();
|
||||||
|
base.OnConfiguring(optionsBuilder);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
// <auto-generated> This file has been auto generated by EF Core Power Tools. </auto-generated>
|
||||||
|
#nullable disable
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
|
||||||
|
namespace Pos.Dispatcher.Database.Models;
|
||||||
|
|
||||||
|
[Table("employee")]
|
||||||
|
[MySqlCharSet("utf8mb4")]
|
||||||
|
[MySqlCollation("utf8mb4_general_ci")]
|
||||||
|
public partial class Employee
|
||||||
|
{
|
||||||
|
[Key]
|
||||||
|
[Column(TypeName = "int(11)")]
|
||||||
|
public int Id { get; set; }
|
||||||
|
|
||||||
|
[Required]
|
||||||
|
[StringLength(50)]
|
||||||
|
public string Name { get; set; }
|
||||||
|
|
||||||
|
[Column(TypeName = "tinyint(4)")]
|
||||||
|
public sbyte IsArchived { get; set; }
|
||||||
|
|
||||||
|
[Column(TypeName = "tinyint(4)")]
|
||||||
|
public sbyte? IsModified { get; set; }
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
// <auto-generated> This file has been auto generated by EF Core Power Tools. </auto-generated>
|
||||||
|
#nullable disable
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
|
||||||
|
namespace Pos.Dispatcher.Database.Models;
|
||||||
|
|
||||||
|
[Table("payment")]
|
||||||
|
public partial class Payment
|
||||||
|
{
|
||||||
|
[Key]
|
||||||
|
[Column(TypeName = "int(11)")]
|
||||||
|
public int Id { get; set; }
|
||||||
|
|
||||||
|
[Column(TypeName = "int(11)")]
|
||||||
|
public int SaleId { get; set; }
|
||||||
|
|
||||||
|
[Precision(20, 6)]
|
||||||
|
public decimal Amount { get; set; }
|
||||||
|
|
||||||
|
[Required]
|
||||||
|
[Column(TypeName = "tinytext")]
|
||||||
|
public string Type { get; set; }
|
||||||
|
}
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
// <auto-generated> This file has been auto generated by EF Core Power Tools. </auto-generated>
|
||||||
|
#nullable disable
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
|
||||||
|
namespace Pos.Dispatcher.Database.Models;
|
||||||
|
|
||||||
|
[Table("product")]
|
||||||
|
[Index("ProductGroupId", Name = "FK_Product_Categories")]
|
||||||
|
[MySqlCharSet("utf8mb4")]
|
||||||
|
[MySqlCollation("utf8mb4_general_ci")]
|
||||||
|
public partial class Product
|
||||||
|
{
|
||||||
|
[Key]
|
||||||
|
[Column(TypeName = "int(11)")]
|
||||||
|
public int Id { get; set; }
|
||||||
|
|
||||||
|
[Required]
|
||||||
|
[Column(TypeName = "tinytext")]
|
||||||
|
public string Name { get; set; }
|
||||||
|
|
||||||
|
[Precision(10, 2)]
|
||||||
|
public decimal Price { get; set; }
|
||||||
|
|
||||||
|
[Column(TypeName = "mediumtext")]
|
||||||
|
public string Description { get; set; }
|
||||||
|
|
||||||
|
[Column(TypeName = "int(11)")]
|
||||||
|
public int ProductGroupId { get; set; }
|
||||||
|
|
||||||
|
[Column(TypeName = "tinyint(4)")]
|
||||||
|
public sbyte IsArchived { get; set; }
|
||||||
|
|
||||||
|
[Column(TypeName = "int(11)")]
|
||||||
|
public int Index { get; set; }
|
||||||
|
|
||||||
|
[Column(TypeName = "tinyint(4)")]
|
||||||
|
public sbyte? IsModified { get; set; }
|
||||||
|
|
||||||
|
[ForeignKey("Id")]
|
||||||
|
[InverseProperty("Product")]
|
||||||
|
public virtual Productgroup IdNavigation { get; set; }
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
// <auto-generated> This file has been auto generated by EF Core Power Tools. </auto-generated>
|
||||||
|
#nullable disable
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
|
||||||
|
namespace Pos.Dispatcher.Database.Models;
|
||||||
|
|
||||||
|
[Table("productgroup")]
|
||||||
|
[MySqlCharSet("utf8mb4")]
|
||||||
|
[MySqlCollation("utf8mb4_general_ci")]
|
||||||
|
public partial class Productgroup
|
||||||
|
{
|
||||||
|
[Key]
|
||||||
|
[Column(TypeName = "int(11)")]
|
||||||
|
public int Id { get; set; }
|
||||||
|
|
||||||
|
[Required]
|
||||||
|
[Column(TypeName = "tinytext")]
|
||||||
|
public string Name { get; set; }
|
||||||
|
|
||||||
|
[Column(TypeName = "tinyint(4)")]
|
||||||
|
public sbyte IsArchived { get; set; }
|
||||||
|
|
||||||
|
[Column(TypeName = "int(11)")]
|
||||||
|
public int Index { get; set; }
|
||||||
|
|
||||||
|
[Column(TypeName = "tinyint(4)")]
|
||||||
|
public sbyte? IsModified { get; set; }
|
||||||
|
|
||||||
|
[InverseProperty("IdNavigation")]
|
||||||
|
public virtual Product Product { get; set; }
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
// <auto-generated> This file has been auto generated by EF Core Power Tools. </auto-generated>
|
||||||
|
#nullable disable
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
|
||||||
|
namespace Pos.Dispatcher.Database.Models;
|
||||||
|
|
||||||
|
[Table("sale")]
|
||||||
|
public partial class Sale
|
||||||
|
{
|
||||||
|
[Key]
|
||||||
|
[Column(TypeName = "int(11)")]
|
||||||
|
public int Id { get; set; }
|
||||||
|
|
||||||
|
[Column(TypeName = "datetime")]
|
||||||
|
public DateTime Time { get; set; }
|
||||||
|
|
||||||
|
[Column(TypeName = "int(11)")]
|
||||||
|
public int EmployeeId { get; set; }
|
||||||
|
|
||||||
|
[Column(TypeName = "tinyint(4)")]
|
||||||
|
public sbyte? IsModified { get; set; }
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
// <auto-generated> This file has been auto generated by EF Core Power Tools. </auto-generated>
|
||||||
|
#nullable disable
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
|
||||||
|
namespace Pos.Dispatcher.Database.Models;
|
||||||
|
|
||||||
|
[Table("sale_line")]
|
||||||
|
public partial class SaleLine
|
||||||
|
{
|
||||||
|
[Key]
|
||||||
|
[Column(TypeName = "int(11)")]
|
||||||
|
public int Id { get; set; }
|
||||||
|
|
||||||
|
[Column(TypeName = "int(11)")]
|
||||||
|
public int SaleId { get; set; }
|
||||||
|
|
||||||
|
[Required]
|
||||||
|
[Column(TypeName = "tinytext")]
|
||||||
|
public string Product { get; set; }
|
||||||
|
|
||||||
|
[Column(TypeName = "smallint(6)")]
|
||||||
|
public short Pieces { get; set; }
|
||||||
|
|
||||||
|
[Precision(20, 6)]
|
||||||
|
public decimal Price { get; set; }
|
||||||
|
|
||||||
|
[Precision(20, 6)]
|
||||||
|
public decimal Total { get; set; }
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net7.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Configuration" Version="7.0.0" />
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="7.0.0" />
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="7.0.0" />
|
||||||
|
<PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="7.0.0" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
{
|
||||||
|
"CodeGenerationMode": 3,
|
||||||
|
"ContextClassName": "PosDispatcherContext",
|
||||||
|
"ContextNamespace": null,
|
||||||
|
"DefaultDacpacSchema": null,
|
||||||
|
"FilterSchemas": false,
|
||||||
|
"IncludeConnectionString": false,
|
||||||
|
"ModelNamespace": null,
|
||||||
|
"OutputContextPath": "Model",
|
||||||
|
"OutputPath": "Models",
|
||||||
|
"PreserveCasingWithRegex": true,
|
||||||
|
"ProjectRootNamespace": "Pos.Dispatcher.Database",
|
||||||
|
"Schemas": null,
|
||||||
|
"SelectedHandlebarsLanguage": 0,
|
||||||
|
"SelectedToBeGenerated": 0,
|
||||||
|
"Tables": [
|
||||||
|
{
|
||||||
|
"Name": "employee",
|
||||||
|
"ObjectType": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Name": "payment",
|
||||||
|
"ObjectType": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Name": "product",
|
||||||
|
"ObjectType": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Name": "productgroup",
|
||||||
|
"ObjectType": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Name": "sale",
|
||||||
|
"ObjectType": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Name": "sale_line",
|
||||||
|
"ObjectType": 0
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"UiHint": "localhost",
|
||||||
|
"UncountableWords": null,
|
||||||
|
"UseBoolPropertiesWithoutDefaultSql": false,
|
||||||
|
"UseDatabaseNames": false,
|
||||||
|
"UseDateOnlyTimeOnly": false,
|
||||||
|
"UseDbContextSplitting": false,
|
||||||
|
"UseFluentApiOnly": false,
|
||||||
|
"UseHandleBars": false,
|
||||||
|
"UseHierarchyId": false,
|
||||||
|
"UseInflector": true,
|
||||||
|
"UseLegacyPluralizer": false,
|
||||||
|
"UseManyToManyEntity": false,
|
||||||
|
"UseNoDefaultConstructor": false,
|
||||||
|
"UseNoObjectFilter": false,
|
||||||
|
"UseNodaTime": false,
|
||||||
|
"UseNullableReferences": false,
|
||||||
|
"UseSchemaFolders": false,
|
||||||
|
"UseSchemaNamespaces": false,
|
||||||
|
"UseSpatial": false,
|
||||||
|
"UseT4": false
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFramework>net7.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<None Remove="appsettings.json" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Content Include="appsettings.json">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
||||||
|
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
||||||
|
</Content>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Hosting" Version="7.0.1" />
|
||||||
|
<PackageReference Include="RestSharp" Version="110.2.0" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\Pos.Dispatcher.Database\Pos.Dispatcher.Database.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
21
PointOfSale/Pos.Dispatcher/Pos.Dispatcher/Program.cs
Normal file
21
PointOfSale/Pos.Dispatcher/Pos.Dispatcher/Program.cs
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
// See https://aka.ms/new-console-template for more information
|
||||||
|
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.Extensions.Configuration;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Microsoft.Extensions.Hosting;
|
||||||
|
using Pomelo.EntityFrameworkCore;
|
||||||
|
using Pos.Dispatcher;
|
||||||
|
using Pos.Dispatcher.Database;
|
||||||
|
using Pos.Dispatcher.Database.Model;
|
||||||
|
|
||||||
|
HostApplicationBuilder builder = Host.CreateApplicationBuilder(args);
|
||||||
|
LoadConfig loadConfig = new LoadConfig();
|
||||||
|
IConfiguration config = loadConfig.ByEnvironment();
|
||||||
|
builder.Services.AddSingleton(config);
|
||||||
|
builder.Services.AddDbContext<PosDispatcherContext>();
|
||||||
|
builder.Services.AddScoped<Synchronize>();
|
||||||
|
using IHost host = builder.Build();
|
||||||
|
|
||||||
|
Synchronize synchronize = host.Services.GetRequiredService<Synchronize>();
|
||||||
|
synchronize.Go();
|
||||||
103
PointOfSale/Pos.Dispatcher/Pos.Dispatcher/Synchronize.cs
Normal file
103
PointOfSale/Pos.Dispatcher/Pos.Dispatcher/Synchronize.cs
Normal file
@@ -0,0 +1,103 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.Extensions.Configuration;
|
||||||
|
using Pos.Dispatcher.Database.Model;
|
||||||
|
using Pos.Dispatcher.Database.Models;
|
||||||
|
using RestSharp;
|
||||||
|
|
||||||
|
namespace Pos.Dispatcher
|
||||||
|
{
|
||||||
|
public class Synchronize
|
||||||
|
{
|
||||||
|
private readonly PosDispatcherContext _context;
|
||||||
|
private readonly IConfiguration _config;
|
||||||
|
private string _apiUrl;
|
||||||
|
private string _apiKey;
|
||||||
|
|
||||||
|
public Synchronize(PosDispatcherContext context, IConfiguration config)
|
||||||
|
{
|
||||||
|
_context = context;
|
||||||
|
_config = config;
|
||||||
|
_apiUrl = _config["PosApi"];
|
||||||
|
_apiKey = _config["ApiKey"];
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Go()
|
||||||
|
{
|
||||||
|
Employee();
|
||||||
|
ProductGroup();
|
||||||
|
Sale();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Employee()
|
||||||
|
{
|
||||||
|
List<Employee> employees = _context.Employees.Where(c => c.IsModified == 1).ToList();
|
||||||
|
foreach (Employee employee in employees)
|
||||||
|
{
|
||||||
|
RestClient client = new RestClient(_apiUrl);
|
||||||
|
client.AddDefaultHeader("ApiKey", _apiKey);
|
||||||
|
var request = new RestRequest("/employee", Method.Post);
|
||||||
|
request.AddJsonBody(employee);
|
||||||
|
RestResponse restResponse = client.Post(request);
|
||||||
|
employee.IsModified = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
_context.SaveChanges();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ProductGroup()
|
||||||
|
{
|
||||||
|
List<Productgroup> productgroups = _context.Productgroups.Where(c => c.IsModified == 1).ToList();
|
||||||
|
foreach (Productgroup product in productgroups)
|
||||||
|
{
|
||||||
|
RestClient client = new RestClient(_apiUrl);
|
||||||
|
client.AddDefaultHeader("ApiKey", _apiKey);
|
||||||
|
var request = new RestRequest("/productgroup", Method.Post);
|
||||||
|
request.AddJsonBody(product);
|
||||||
|
RestResponse response = client.Post(request);
|
||||||
|
product.IsModified = 0;
|
||||||
|
}
|
||||||
|
_context.SaveChanges();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Sale()
|
||||||
|
{
|
||||||
|
List<Sale> sales = _context.Sales.Where(c => c.IsModified == 1).ToList();
|
||||||
|
foreach (Sale sale in sales)
|
||||||
|
{
|
||||||
|
RestClient client = new RestClient(_apiUrl);
|
||||||
|
client.AddDefaultHeader("ApiKey", _apiKey);
|
||||||
|
var request = new RestRequest("/sale", Method.Post);
|
||||||
|
request.AddJsonBody(sale);
|
||||||
|
RestResponse response = client.Post(request);
|
||||||
|
sale.IsModified = 0;
|
||||||
|
|
||||||
|
List<SaleLine> saleLines = _context.SaleLines.Where(c => c.SaleId == sale.Id).ToList();
|
||||||
|
foreach (SaleLine saleLine in saleLines)
|
||||||
|
{
|
||||||
|
client = new RestClient(_apiUrl);
|
||||||
|
client.AddDefaultHeader("ApiKey", _apiKey);
|
||||||
|
request = new RestRequest("/saleline", Method.Post);
|
||||||
|
request.AddJsonBody(saleLine);
|
||||||
|
response = client.Post(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Payment> payments = _context.Payments.Where(c => c.SaleId == sale.Id).ToList();
|
||||||
|
foreach (Payment payment in payments)
|
||||||
|
{
|
||||||
|
client = new RestClient(_apiUrl);
|
||||||
|
client.AddDefaultHeader("ApiKey", _apiKey);
|
||||||
|
request = new RestRequest("/payment", Method.Post);
|
||||||
|
request.AddJsonBody(payment);
|
||||||
|
response = client.Post(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
sale.IsModified = 0;
|
||||||
|
}
|
||||||
|
_context.SaveChanges();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
12
PointOfSale/Pos.Dispatcher/Pos.Dispatcher/appsettings.json
Normal file
12
PointOfSale/Pos.Dispatcher/Pos.Dispatcher/appsettings.json
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"Logging": {
|
||||||
|
"LogLevel": {
|
||||||
|
"Default": "Information",
|
||||||
|
"Microsoft.AspNetCore": "Warning"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"AllowedHosts": "*",
|
||||||
|
"MariaSqlServer": "Data Source=localhost;Initial Catalog=PointOfSale;Persist Security Info=False;User ID=root",
|
||||||
|
"ApiKey": "ad0YfMYm5bdVGjmXkJBOdNggQaWtkB9nzyQv68GAcB7mpf9onGBP9j3DJ46S7go30NwaQgoZBNS7hZDOM79KTyU3K2ysMW2x4mWGHOkETJmWadaMXBTGpoWn0ef9KiUN",
|
||||||
|
"PosApi": "http://localhost:53151"
|
||||||
|
}
|
||||||
21
PointOfSale/Pos.EpsonPrinter/EncodingHelper.cs
Normal file
21
PointOfSale/Pos.EpsonPrinter/EncodingHelper.cs
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace EpsonReceiptPrinter;
|
||||||
|
|
||||||
|
public static class EncodingHelper
|
||||||
|
{
|
||||||
|
static EncodingHelper()
|
||||||
|
{
|
||||||
|
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Encoding GetEncodingForCodePage(PrinterCodePage codePage) =>
|
||||||
|
codePage switch
|
||||||
|
{
|
||||||
|
PrinterCodePage.PC865_Nordic => Encoding.GetEncoding(865),
|
||||||
|
PrinterCodePage.PC850_Multilingual => Encoding.GetEncoding(850),
|
||||||
|
PrinterCodePage.PC858_Euro => Encoding.GetEncoding(858),
|
||||||
|
PrinterCodePage.WPC1252 => Encoding.GetEncoding(1252),
|
||||||
|
_ => Encoding.GetEncoding(865)
|
||||||
|
};
|
||||||
|
}
|
||||||
42
PointOfSale/Pos.EpsonPrinter/EpsonNetworkReceiptPrinter.cs
Normal file
42
PointOfSale/Pos.EpsonPrinter/EpsonNetworkReceiptPrinter.cs
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
using System.Net.Sockets;
|
||||||
|
|
||||||
|
namespace EpsonReceiptPrinter;
|
||||||
|
|
||||||
|
public sealed class EpsonNetworkReceiptPrinter : IReceiptPrinter
|
||||||
|
{
|
||||||
|
private readonly string _host;
|
||||||
|
private readonly int _port;
|
||||||
|
private readonly PrinterCodePage _codePage;
|
||||||
|
|
||||||
|
public EpsonNetworkReceiptPrinter(string host, int port = 9100, PrinterCodePage codePage = PrinterCodePage.PC865_Nordic)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(host))
|
||||||
|
{
|
||||||
|
throw new ArgumentException("Host must be provided.", nameof(host));
|
||||||
|
}
|
||||||
|
|
||||||
|
_host = host;
|
||||||
|
_port = port;
|
||||||
|
_codePage = codePage;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task PrintAsync(Receipt receipt, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
ArgumentNullException.ThrowIfNull(receipt);
|
||||||
|
|
||||||
|
var data = ReceiptFormatter.Format(receipt, _codePage);
|
||||||
|
await PrintRawAsync(data, cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task PrintRawAsync(byte[] data, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
ArgumentNullException.ThrowIfNull(data);
|
||||||
|
|
||||||
|
using var client = new TcpClient();
|
||||||
|
await client.ConnectAsync(_host, _port, cancellationToken);
|
||||||
|
|
||||||
|
await using var stream = client.GetStream();
|
||||||
|
await stream.WriteAsync(data, cancellationToken);
|
||||||
|
await stream.FlushAsync(cancellationToken);
|
||||||
|
}
|
||||||
|
}
|
||||||
10
PointOfSale/Pos.EpsonPrinter/EpsonReceiptPrinter.csproj
Normal file
10
PointOfSale/Pos.EpsonPrinter/EpsonReceiptPrinter.csproj
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
<GeneratePackageOnBuild>false</GeneratePackageOnBuild>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
147
PointOfSale/Pos.EpsonPrinter/EscPosBuilder.cs
Normal file
147
PointOfSale/Pos.EpsonPrinter/EscPosBuilder.cs
Normal file
@@ -0,0 +1,147 @@
|
|||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace EpsonReceiptPrinter;
|
||||||
|
|
||||||
|
public sealed class EscPosBuilder
|
||||||
|
{
|
||||||
|
private readonly List<byte> _buffer = new();
|
||||||
|
private readonly Encoding _encoding;
|
||||||
|
private PrinterCodePage _codePage;
|
||||||
|
|
||||||
|
public EscPosBuilder(PrinterCodePage codePage = PrinterCodePage.PC865_Nordic, Encoding? encoding = null)
|
||||||
|
{
|
||||||
|
_codePage = codePage;
|
||||||
|
_encoding = encoding ?? EncodingHelper.GetEncodingForCodePage(codePage);
|
||||||
|
}
|
||||||
|
|
||||||
|
public EscPosBuilder Initialize()
|
||||||
|
{
|
||||||
|
_buffer.AddRange(EscPosCommands.Initialize);
|
||||||
|
_buffer.AddRange(EscPosCommands.SelectCodePage(_codePage));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public EscPosBuilder SelectCodePage(PrinterCodePage codePage)
|
||||||
|
{
|
||||||
|
_codePage = codePage;
|
||||||
|
_buffer.AddRange(EscPosCommands.SelectCodePage(codePage));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public EscPosBuilder AlignLeft()
|
||||||
|
{
|
||||||
|
_buffer.AddRange(EscPosCommands.AlignLeft);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public EscPosBuilder AlignCenter()
|
||||||
|
{
|
||||||
|
_buffer.AddRange(EscPosCommands.AlignCenter);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public EscPosBuilder AlignRight()
|
||||||
|
{
|
||||||
|
_buffer.AddRange(EscPosCommands.AlignRight);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public EscPosBuilder BoldOn()
|
||||||
|
{
|
||||||
|
_buffer.AddRange(EscPosCommands.BoldOn);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public EscPosBuilder BoldOff()
|
||||||
|
{
|
||||||
|
_buffer.AddRange(EscPosCommands.BoldOff);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public EscPosBuilder UnderlineOn()
|
||||||
|
{
|
||||||
|
_buffer.AddRange(EscPosCommands.UnderlineOn);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public EscPosBuilder UnderlineOff()
|
||||||
|
{
|
||||||
|
_buffer.AddRange(EscPosCommands.UnderlineOff);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public EscPosBuilder SetTextSize(TextSize size)
|
||||||
|
{
|
||||||
|
_buffer.AddRange(EscPosCommands.TextSize(size));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public EscPosBuilder SetTextSize(int widthMultiplier, int heightMultiplier)
|
||||||
|
{
|
||||||
|
_buffer.AddRange(EscPosCommands.TextSize(widthMultiplier, heightMultiplier));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public EscPosBuilder Write(string text)
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrEmpty(text))
|
||||||
|
{
|
||||||
|
_buffer.AddRange(_encoding.GetBytes(text));
|
||||||
|
}
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public EscPosBuilder WriteLine(string? text = null)
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrEmpty(text))
|
||||||
|
{
|
||||||
|
_buffer.AddRange(_encoding.GetBytes(text));
|
||||||
|
}
|
||||||
|
|
||||||
|
_buffer.Add(0x0A);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public EscPosBuilder Feed(int lines = 1)
|
||||||
|
{
|
||||||
|
_buffer.AddRange(EscPosCommands.Feed(lines));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public EscPosBuilder Cut(bool partial = false)
|
||||||
|
{
|
||||||
|
_buffer.AddRange(partial ? EscPosCommands.CutPartial() : EscPosCommands.CutFull());
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public EscPosBuilder OpenCashDrawer()
|
||||||
|
{
|
||||||
|
_buffer.AddRange(EscPosCommands.OpenCashDrawer());
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public EscPosBuilder Separator(int width = 42, char character = '-')
|
||||||
|
{
|
||||||
|
return WriteLine(new string(character, width));
|
||||||
|
}
|
||||||
|
|
||||||
|
public EscPosBuilder WriteColumns(string left, string? right, int totalWidth = 42)
|
||||||
|
{
|
||||||
|
left ??= string.Empty;
|
||||||
|
right ??= string.Empty;
|
||||||
|
|
||||||
|
if (left.Length + right.Length >= totalWidth)
|
||||||
|
{
|
||||||
|
WriteLine(left);
|
||||||
|
WriteLine(right.PadLeft(totalWidth));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
var spaces = totalWidth - left.Length - right.Length;
|
||||||
|
WriteLine(left + new string(' ', spaces) + right);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] Build() => _buffer.ToArray();
|
||||||
|
}
|
||||||
63
PointOfSale/Pos.EpsonPrinter/EscPosCommands.cs
Normal file
63
PointOfSale/Pos.EpsonPrinter/EscPosCommands.cs
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
namespace EpsonReceiptPrinter;
|
||||||
|
|
||||||
|
public static class EscPosCommands
|
||||||
|
{
|
||||||
|
public static readonly byte[] Initialize = [0x1B, 0x40];
|
||||||
|
|
||||||
|
public static readonly byte[] BoldOn = [0x1B, 0x45, 0x01];
|
||||||
|
public static readonly byte[] BoldOff = [0x1B, 0x45, 0x00];
|
||||||
|
|
||||||
|
public static readonly byte[] UnderlineOn = [0x1B, 0x2D, 0x01];
|
||||||
|
public static readonly byte[] UnderlineOff = [0x1B, 0x2D, 0x00];
|
||||||
|
|
||||||
|
public static readonly byte[] AlignLeft = [0x1B, 0x61, 0x00];
|
||||||
|
public static readonly byte[] AlignCenter = [0x1B, 0x61, 0x01];
|
||||||
|
public static readonly byte[] AlignRight = [0x1B, 0x61, 0x02];
|
||||||
|
|
||||||
|
public static readonly byte[] FontA = [0x1B, 0x4D, 0x00];
|
||||||
|
public static readonly byte[] FontB = [0x1B, 0x4D, 0x01];
|
||||||
|
|
||||||
|
public static byte[] Feed(int lines)
|
||||||
|
{
|
||||||
|
if (lines < 0 || lines > 255)
|
||||||
|
{
|
||||||
|
throw new ArgumentOutOfRangeException(nameof(lines));
|
||||||
|
}
|
||||||
|
|
||||||
|
return [0x1B, 0x64, (byte)lines];
|
||||||
|
}
|
||||||
|
|
||||||
|
public static byte[] CutFull() => [0x1D, 0x56, 0x00];
|
||||||
|
|
||||||
|
public static byte[] CutPartial() => [0x1D, 0x56, 0x01];
|
||||||
|
|
||||||
|
public static byte[] OpenCashDrawer() => [0x1B, 0x70, 0x00, 0x19, 0xFA];
|
||||||
|
|
||||||
|
public static byte[] SelectCodePage(PrinterCodePage codePage) => [0x1B, 0x74, (byte)codePage];
|
||||||
|
|
||||||
|
public static byte[] TextSize(TextSize size) =>
|
||||||
|
size switch
|
||||||
|
{
|
||||||
|
TextSize.Normal => [0x1D, 0x21, 0x00],
|
||||||
|
TextSize.DoubleWidth => [0x1D, 0x21, 0x10],
|
||||||
|
TextSize.DoubleHeight => [0x1D, 0x21, 0x01],
|
||||||
|
TextSize.DoubleWidthAndHeight => [0x1D, 0x21, 0x11],
|
||||||
|
_ => [0x1D, 0x21, 0x00]
|
||||||
|
};
|
||||||
|
|
||||||
|
public static byte[] TextSize(int widthMultiplier, int heightMultiplier)
|
||||||
|
{
|
||||||
|
if (widthMultiplier < 1 || widthMultiplier > 8)
|
||||||
|
{
|
||||||
|
throw new ArgumentOutOfRangeException(nameof(widthMultiplier));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (heightMultiplier < 1 || heightMultiplier > 8)
|
||||||
|
{
|
||||||
|
throw new ArgumentOutOfRangeException(nameof(heightMultiplier));
|
||||||
|
}
|
||||||
|
|
||||||
|
var value = (byte)(((widthMultiplier - 1) << 4) | (heightMultiplier - 1));
|
||||||
|
return [0x1D, 0x21, value];
|
||||||
|
}
|
||||||
|
}
|
||||||
7
PointOfSale/Pos.EpsonPrinter/IReceiptPrinter.cs
Normal file
7
PointOfSale/Pos.EpsonPrinter/IReceiptPrinter.cs
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
namespace EpsonReceiptPrinter;
|
||||||
|
|
||||||
|
public interface IReceiptPrinter
|
||||||
|
{
|
||||||
|
Task PrintAsync(Receipt receipt, CancellationToken cancellationToken = default);
|
||||||
|
Task PrintRawAsync(byte[] data, CancellationToken cancellationToken = default);
|
||||||
|
}
|
||||||
13
PointOfSale/Pos.EpsonPrinter/PrinterCodePage.cs
Normal file
13
PointOfSale/Pos.EpsonPrinter/PrinterCodePage.cs
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
namespace EpsonReceiptPrinter;
|
||||||
|
|
||||||
|
public enum PrinterCodePage
|
||||||
|
{
|
||||||
|
PC437_USA = 0,
|
||||||
|
Katakana = 1,
|
||||||
|
PC850_Multilingual = 2,
|
||||||
|
PC860_Portuguese = 3,
|
||||||
|
PC863_CanadianFrench = 4,
|
||||||
|
PC865_Nordic = 5,
|
||||||
|
WPC1252 = 16,
|
||||||
|
PC858_Euro = 19
|
||||||
|
}
|
||||||
31
PointOfSale/Pos.EpsonPrinter/Receipt.cs
Normal file
31
PointOfSale/Pos.EpsonPrinter/Receipt.cs
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
namespace EpsonReceiptPrinter;
|
||||||
|
|
||||||
|
public sealed class Receipt
|
||||||
|
{
|
||||||
|
public string? Header { get; set; }
|
||||||
|
public string? SubHeader { get; set; }
|
||||||
|
public List<ReceiptLine> Lines { get; } = new();
|
||||||
|
public string? Footer { get; set; }
|
||||||
|
public bool CutPaper { get; set; } = true;
|
||||||
|
public int PaperWidthCharacters { get; set; } = 42;
|
||||||
|
}
|
||||||
|
|
||||||
|
public sealed class ReceiptLine
|
||||||
|
{
|
||||||
|
public ReceiptLine()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public ReceiptLine(string left, string? right = null, bool emphasize = false, TextSize textSize = TextSize.Normal)
|
||||||
|
{
|
||||||
|
Left = left;
|
||||||
|
Right = right;
|
||||||
|
Emphasize = emphasize;
|
||||||
|
TextSize = textSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Left { get; set; } = string.Empty;
|
||||||
|
public string? Right { get; set; }
|
||||||
|
public bool Emphasize { get; set; }
|
||||||
|
public TextSize TextSize { get; set; } = TextSize.Normal;
|
||||||
|
}
|
||||||
72
PointOfSale/Pos.EpsonPrinter/ReceiptFormatter.cs
Normal file
72
PointOfSale/Pos.EpsonPrinter/ReceiptFormatter.cs
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
namespace EpsonReceiptPrinter;
|
||||||
|
|
||||||
|
public static class ReceiptFormatter
|
||||||
|
{
|
||||||
|
public static byte[] Format(Receipt receipt, PrinterCodePage codePage = PrinterCodePage.PC865_Nordic)
|
||||||
|
{
|
||||||
|
ArgumentNullException.ThrowIfNull(receipt);
|
||||||
|
|
||||||
|
var width = receipt.PaperWidthCharacters <= 0 ? 42 : receipt.PaperWidthCharacters;
|
||||||
|
|
||||||
|
var builder = new EscPosBuilder(codePage)
|
||||||
|
.Initialize()
|
||||||
|
.AlignCenter();
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(receipt.Header))
|
||||||
|
{
|
||||||
|
builder
|
||||||
|
.SetTextSize(TextSize.DoubleWidthAndHeight)
|
||||||
|
.BoldOn()
|
||||||
|
.WriteLine(receipt.Header)
|
||||||
|
.BoldOff()
|
||||||
|
.SetTextSize(TextSize.Normal);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(receipt.SubHeader))
|
||||||
|
{
|
||||||
|
builder.WriteLine(receipt.SubHeader);
|
||||||
|
}
|
||||||
|
|
||||||
|
builder
|
||||||
|
.Feed(1)
|
||||||
|
.AlignLeft()
|
||||||
|
.Separator(width);
|
||||||
|
|
||||||
|
foreach (var line in receipt.Lines)
|
||||||
|
{
|
||||||
|
builder.SetTextSize(line.TextSize);
|
||||||
|
|
||||||
|
if (line.Emphasize)
|
||||||
|
{
|
||||||
|
builder.BoldOn();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
builder.BoldOff();
|
||||||
|
}
|
||||||
|
|
||||||
|
builder.WriteColumns(line.Left, line.Right, width);
|
||||||
|
builder.SetTextSize(TextSize.Normal);
|
||||||
|
builder.BoldOff();
|
||||||
|
}
|
||||||
|
|
||||||
|
builder
|
||||||
|
.Separator(width)
|
||||||
|
.Feed(1)
|
||||||
|
.AlignCenter();
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(receipt.Footer))
|
||||||
|
{
|
||||||
|
builder.WriteLine(receipt.Footer);
|
||||||
|
}
|
||||||
|
|
||||||
|
builder.Feed(3);
|
||||||
|
|
||||||
|
if (receipt.CutPaper)
|
||||||
|
{
|
||||||
|
builder.Cut();
|
||||||
|
}
|
||||||
|
|
||||||
|
return builder.Build();
|
||||||
|
}
|
||||||
|
}
|
||||||
9
PointOfSale/Pos.EpsonPrinter/TextSize.cs
Normal file
9
PointOfSale/Pos.EpsonPrinter/TextSize.cs
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
namespace EpsonReceiptPrinter;
|
||||||
|
|
||||||
|
public enum TextSize
|
||||||
|
{
|
||||||
|
Normal,
|
||||||
|
DoubleWidth,
|
||||||
|
DoubleHeight,
|
||||||
|
DoubleWidthAndHeight
|
||||||
|
}
|
||||||
12
PointOfSale/Pos.Ui/Database/.config/dotnet-tools.json
Normal file
12
PointOfSale/Pos.Ui/Database/.config/dotnet-tools.json
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"version": 1,
|
||||||
|
"isRoot": true,
|
||||||
|
"tools": {
|
||||||
|
"dotnet-ef": {
|
||||||
|
"version": "5.0.9",
|
||||||
|
"commands": [
|
||||||
|
"dotnet-ef"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
16
PointOfSale/Pos.Ui/Database/Database.csproj
Normal file
16
PointOfSale/Pos.Ui/Database/Database.csproj
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="7.0.2" />
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Configuration" Version="7.0.0" />
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="7.0.0" />
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="7.0.0" />
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="7.0.0" />
|
||||||
|
<PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="7.0.0" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
60
PointOfSale/Pos.Ui/Database/LoadConfig.cs
Normal file
60
PointOfSale/Pos.Ui/Database/LoadConfig.cs
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.Extensions.Configuration;
|
||||||
|
|
||||||
|
namespace Pos
|
||||||
|
{
|
||||||
|
public class LoadConfig
|
||||||
|
{
|
||||||
|
private string dir;
|
||||||
|
public LoadConfig()
|
||||||
|
{
|
||||||
|
dir = AppDomain.CurrentDomain.BaseDirectory;
|
||||||
|
}
|
||||||
|
public IConfiguration ByEnvironment()
|
||||||
|
{
|
||||||
|
//Console.Out.WriteLine($"Json path: {dir}");
|
||||||
|
#if DEBUG
|
||||||
|
|
||||||
|
var config = new ConfigurationBuilder()
|
||||||
|
.SetBasePath(dir)
|
||||||
|
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
|
||||||
|
.AddJsonFile("appsettings.Development.json", optional: true, reloadOnChange: true)
|
||||||
|
.Build();
|
||||||
|
return config;
|
||||||
|
|
||||||
|
#else
|
||||||
|
var config = new ConfigurationBuilder()
|
||||||
|
.SetBasePath(dir)
|
||||||
|
.AddJsonFile("appsettings.Production.json", optional: true, reloadOnChange: true)
|
||||||
|
.Build();
|
||||||
|
return config;
|
||||||
|
#endif
|
||||||
|
//Running in a environment that not is supported in this setup
|
||||||
|
throw new Exception("HostingEnvironment is not supported! This config setup only supports Development or Production");
|
||||||
|
}
|
||||||
|
|
||||||
|
public IConfiguration DebugConfiguration()
|
||||||
|
{
|
||||||
|
var config = new ConfigurationBuilder()
|
||||||
|
.SetBasePath(dir)
|
||||||
|
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
|
||||||
|
.AddJsonFile("appsettings.Development.json", optional: true, reloadOnChange: true)
|
||||||
|
.Build();
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IConfiguration ReleaseConfiguration()
|
||||||
|
{
|
||||||
|
var config = new ConfigurationBuilder()
|
||||||
|
.SetBasePath(dir)
|
||||||
|
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
|
||||||
|
.AddJsonFile("appsettings.Production.json", optional: true, reloadOnChange: true)
|
||||||
|
.Build();
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
20
PointOfSale/Pos.Ui/Database/Models/EmployeeEntity.cs
Normal file
20
PointOfSale/Pos.Ui/Database/Models/EmployeeEntity.cs
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Database.Models
|
||||||
|
{
|
||||||
|
[Table("employee")]
|
||||||
|
public class EmployeeEntity
|
||||||
|
{
|
||||||
|
[Key]
|
||||||
|
public int Id { get; set; }
|
||||||
|
public string Name { get; set; }
|
||||||
|
public bool IsArchived { get; set; }
|
||||||
|
public bool IsModified { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
21
PointOfSale/Pos.Ui/Database/Models/PaymentEntity.cs
Normal file
21
PointOfSale/Pos.Ui/Database/Models/PaymentEntity.cs
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Database.Models
|
||||||
|
{
|
||||||
|
[Table("payment")]
|
||||||
|
public class PaymentEntity
|
||||||
|
{
|
||||||
|
[Key]
|
||||||
|
public int Id { get; set; }
|
||||||
|
public int SaleId { get; set; }
|
||||||
|
public decimal Amount { get; set;}
|
||||||
|
public string Type { get; set; }
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
22
PointOfSale/Pos.Ui/Database/Models/ProductEntity.cs
Normal file
22
PointOfSale/Pos.Ui/Database/Models/ProductEntity.cs
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
|
|
||||||
|
namespace Database.Models
|
||||||
|
{
|
||||||
|
[Table("product")]
|
||||||
|
public class ProductEntity
|
||||||
|
{
|
||||||
|
[Key]
|
||||||
|
public int Id { get; set; }
|
||||||
|
public string Name { get; set; }
|
||||||
|
public decimal Price { get; set; }
|
||||||
|
public string Description { get; set; }
|
||||||
|
public bool IsArchived { get; set; }
|
||||||
|
public int Index { get; set; }
|
||||||
|
public bool IsModified { get; set; }
|
||||||
|
public int ProductGroupId { get; set; }
|
||||||
|
|
||||||
|
[ForeignKey(nameof(ProductGroupId))]
|
||||||
|
public ProductGroupEntity ProductGroup { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
22
PointOfSale/Pos.Ui/Database/Models/ProductGroupEntity.cs
Normal file
22
PointOfSale/Pos.Ui/Database/Models/ProductGroupEntity.cs
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Database.Models
|
||||||
|
{
|
||||||
|
[Table("productgroup")]
|
||||||
|
public class ProductGroupEntity
|
||||||
|
{
|
||||||
|
[Key]
|
||||||
|
public int Id { get; set; }
|
||||||
|
public string Name { get; set; }
|
||||||
|
public bool IsArchived { get; set; }
|
||||||
|
public int Index { get; set; }
|
||||||
|
|
||||||
|
public ICollection<ProductEntity> Products { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
20
PointOfSale/Pos.Ui/Database/Models/SaleEntity.cs
Normal file
20
PointOfSale/Pos.Ui/Database/Models/SaleEntity.cs
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Database.Models
|
||||||
|
{
|
||||||
|
[Table("sale")]
|
||||||
|
public class SaleEntity
|
||||||
|
{
|
||||||
|
[Key]
|
||||||
|
public int Id { get; set; }
|
||||||
|
public DateTime Time { get; set; }
|
||||||
|
public int EmployeeId { get; set; }
|
||||||
|
public bool IsModified { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
22
PointOfSale/Pos.Ui/Database/Models/SaleLineEntity.cs
Normal file
22
PointOfSale/Pos.Ui/Database/Models/SaleLineEntity.cs
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Database.Models
|
||||||
|
{
|
||||||
|
[Table("sale_line")]
|
||||||
|
public class SaleLineEntity
|
||||||
|
{
|
||||||
|
[Key]
|
||||||
|
public int Id { get; set; }
|
||||||
|
public int SaleId { get; set; }
|
||||||
|
public string Product { get; set; }
|
||||||
|
public int Pieces { get; set; }
|
||||||
|
public decimal Price { get; set; }
|
||||||
|
public decimal Total { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
35
PointOfSale/Pos.Ui/Database/PosDbContext.cs
Normal file
35
PointOfSale/Pos.Ui/Database/PosDbContext.cs
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
using Database.Models;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.Extensions.Configuration;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Pos;
|
||||||
|
|
||||||
|
|
||||||
|
namespace Database
|
||||||
|
{
|
||||||
|
public class PosDbContext : DbContext
|
||||||
|
{
|
||||||
|
|
||||||
|
public DbSet<EmployeeEntity> Employee { get; set; }
|
||||||
|
public DbSet<ProductGroupEntity> ProductGroups { get; set; }
|
||||||
|
public DbSet<ProductEntity> Products { get; set; }
|
||||||
|
public DbSet<SaleEntity> Sales { get; set; }
|
||||||
|
public DbSet<SaleLineEntity> SalesLines { get; set; }
|
||||||
|
public DbSet<PaymentEntity> Payment { get; set; }
|
||||||
|
|
||||||
|
protected override void OnConfiguring(
|
||||||
|
DbContextOptionsBuilder optionsBuilder)
|
||||||
|
{
|
||||||
|
LoadConfig l = new LoadConfig();
|
||||||
|
IConfiguration config = l.ByEnvironment();
|
||||||
|
string connectionString = config["MariaSqlServer"].ToString();
|
||||||
|
optionsBuilder
|
||||||
|
.UseMySql(connectionString,ServerVersion.AutoDetect(connectionString))
|
||||||
|
.UseLoggerFactory(LoggerFactory.Create(b => b
|
||||||
|
.AddFilter(level => level >= LogLevel.Information)))
|
||||||
|
.EnableSensitiveDataLogging()
|
||||||
|
.EnableDetailedErrors();
|
||||||
|
base.OnConfiguring(optionsBuilder);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
62
PointOfSale/Pos.Ui/Database/Repository/EmployeeRepository.cs
Normal file
62
PointOfSale/Pos.Ui/Database/Repository/EmployeeRepository.cs
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Database.Models;
|
||||||
|
using Microsoft.Extensions.Configuration;
|
||||||
|
|
||||||
|
namespace Database.Repository
|
||||||
|
{
|
||||||
|
public class EmployeeRepository : IDisposable
|
||||||
|
{
|
||||||
|
|
||||||
|
public void Add(string name)
|
||||||
|
{
|
||||||
|
EmployeeEntity employee = new EmployeeEntity();
|
||||||
|
employee.Name = name;
|
||||||
|
employee.IsModified = true;
|
||||||
|
using PosDbContext context = new PosDbContext();
|
||||||
|
context.Employee.Add(employee);
|
||||||
|
context.SaveChanges();
|
||||||
|
}
|
||||||
|
|
||||||
|
public EmployeeEntity Get(int employeeId)
|
||||||
|
{
|
||||||
|
using PosDbContext context = new PosDbContext();
|
||||||
|
EmployeeEntity employeeEntity = context.Employee.First(c => c.Id == employeeId);
|
||||||
|
return employeeEntity;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<EmployeeEntity> GetAll()
|
||||||
|
{
|
||||||
|
using PosDbContext context = new PosDbContext();
|
||||||
|
List<EmployeeEntity> staffs = context.Employee.Where(c => c.IsArchived == false).ToList();
|
||||||
|
|
||||||
|
return staffs;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Edit(int id, string name)
|
||||||
|
{
|
||||||
|
using PosDbContext context = new PosDbContext();
|
||||||
|
EmployeeEntity employee = context.Employee.Single(c => c.Id == id);
|
||||||
|
employee.Name = name;
|
||||||
|
employee.IsModified = true;
|
||||||
|
context.SaveChanges();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Delete(int id)
|
||||||
|
{
|
||||||
|
using PosDbContext context = new PosDbContext();
|
||||||
|
EmployeeEntity employee = context.Employee.Single(c => c.Id == id);
|
||||||
|
employee.IsArchived = true;
|
||||||
|
employee.IsModified = true;
|
||||||
|
context.SaveChanges();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,79 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Database.Models;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
|
||||||
|
namespace Database.Repository
|
||||||
|
{
|
||||||
|
public class ProductGroupRepository
|
||||||
|
{
|
||||||
|
public List<ProductGroupEntity> GetAll()
|
||||||
|
{
|
||||||
|
using PosDbContext context = new PosDbContext();
|
||||||
|
List<ProductGroupEntity> productGroups = context.ProductGroups
|
||||||
|
.Include(c => c.Products)
|
||||||
|
.Where(c => c.IsArchived == false)
|
||||||
|
.OrderBy(c => c.Index)
|
||||||
|
.ToList();
|
||||||
|
return productGroups;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ProductGroupEntity Get(int id)
|
||||||
|
{
|
||||||
|
using PosDbContext context = new PosDbContext();
|
||||||
|
ProductGroupEntity product = context.ProductGroups.Single(c => c.Id == id);
|
||||||
|
return product;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Add(string name)
|
||||||
|
{
|
||||||
|
ProductGroupEntity productGroup = new ProductGroupEntity();
|
||||||
|
productGroup.Name = name;
|
||||||
|
using PosDbContext context = new PosDbContext();
|
||||||
|
//Get the highest index
|
||||||
|
ProductGroupEntity highest = context.ProductGroups.OrderByDescending(c => c.Index).Take(1).FirstOrDefault();
|
||||||
|
if(highest == null)
|
||||||
|
{
|
||||||
|
highest = new ProductGroupEntity();
|
||||||
|
highest.Index = 0;
|
||||||
|
}
|
||||||
|
productGroup.Index = highest.Index + 1;
|
||||||
|
context.ProductGroups.Add(productGroup);
|
||||||
|
context.SaveChanges();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Edit(string name, int id)
|
||||||
|
{
|
||||||
|
using PosDbContext context = new PosDbContext();
|
||||||
|
ProductGroupEntity productGroup = context.ProductGroups.Single(c => c.Id == id);
|
||||||
|
productGroup.Name = name;
|
||||||
|
context.SaveChanges();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Archive(int id)
|
||||||
|
{
|
||||||
|
using PosDbContext context = new PosDbContext();
|
||||||
|
ProductGroupEntity productGroup = context.ProductGroups.Single(c => c.Id == id);
|
||||||
|
productGroup.IsArchived = true;
|
||||||
|
context.SaveChanges();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetIndex(int id, int index)
|
||||||
|
{
|
||||||
|
using PosDbContext context = new PosDbContext();
|
||||||
|
ProductGroupEntity productGroup = context.ProductGroups.Single(c => c.Id == id);
|
||||||
|
productGroup.Index = index;
|
||||||
|
context.SaveChanges();
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Any()
|
||||||
|
{
|
||||||
|
using PosDbContext context = new PosDbContext();
|
||||||
|
bool any = context.ProductGroups.Any();
|
||||||
|
return any;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
87
PointOfSale/Pos.Ui/Database/Repository/ProductRepository.cs
Normal file
87
PointOfSale/Pos.Ui/Database/Repository/ProductRepository.cs
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using Database.Models;
|
||||||
|
|
||||||
|
namespace Database.Repository
|
||||||
|
{
|
||||||
|
public class ProductRepository
|
||||||
|
{
|
||||||
|
public List<ProductEntity> GetAll()
|
||||||
|
{
|
||||||
|
using PosDbContext context = new PosDbContext();
|
||||||
|
List<ProductEntity> products = context.Products
|
||||||
|
.Where(c => c.IsArchived == false)
|
||||||
|
.OrderBy(c => c.Index)
|
||||||
|
.ToList();
|
||||||
|
return products;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<ProductEntity> GetByProductGroup(int id)
|
||||||
|
{
|
||||||
|
using PosDbContext context = new PosDbContext();
|
||||||
|
List<ProductEntity> products = context.Products
|
||||||
|
.Where(c => c.ProductGroupId == id)
|
||||||
|
.Where(c => c.IsArchived == false)
|
||||||
|
.OrderBy(c => c.Index)
|
||||||
|
.ToList();
|
||||||
|
return products;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetIndex(int id, int index)
|
||||||
|
{
|
||||||
|
using PosDbContext context = new PosDbContext();
|
||||||
|
ProductEntity product = context.Products.Single(c => c.Id == id);
|
||||||
|
product.Index = index;
|
||||||
|
product.IsModified = true;
|
||||||
|
context.SaveChanges();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ProductEntity GetById(int id)
|
||||||
|
{
|
||||||
|
using PosDbContext context = new PosDbContext();
|
||||||
|
ProductEntity product = context.Products.Single(c => c.Id == id);
|
||||||
|
return product;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Update(int id, int productGroupId, string name)
|
||||||
|
{
|
||||||
|
using PosDbContext context = new PosDbContext();
|
||||||
|
ProductEntity dbProduct = context.Products.Single(c => c.Id == id);
|
||||||
|
dbProduct.ProductGroupId = productGroupId;
|
||||||
|
dbProduct.Name = name;
|
||||||
|
dbProduct.IsModified = true;
|
||||||
|
context.SaveChanges();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Archive(int id)
|
||||||
|
{
|
||||||
|
using PosDbContext context = new PosDbContext();
|
||||||
|
ProductEntity dbProduct = context.Products.Single(c => c.Id == id);
|
||||||
|
dbProduct.IsArchived = true;
|
||||||
|
dbProduct.IsModified = true;
|
||||||
|
context.SaveChanges();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Add(string name, int productGroupId)
|
||||||
|
{
|
||||||
|
|
||||||
|
ProductEntity product = new ProductEntity();
|
||||||
|
product.Name = name;
|
||||||
|
product.ProductGroupId = productGroupId;
|
||||||
|
using PosDbContext context = new PosDbContext();
|
||||||
|
//Get the highest index
|
||||||
|
ProductEntity highest = context.Products.OrderByDescending(c => c.Index).Take(1).FirstOrDefault();
|
||||||
|
if (highest == null)
|
||||||
|
{
|
||||||
|
highest = new ProductEntity();
|
||||||
|
highest.Index = 0;
|
||||||
|
}
|
||||||
|
product.Index = highest.Index + 1;
|
||||||
|
product.IsModified = true;
|
||||||
|
context.Products.Add(product);
|
||||||
|
context.SaveChanges();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
83
PointOfSale/Pos.Ui/Database/Repository/SaleRepository.cs
Normal file
83
PointOfSale/Pos.Ui/Database/Repository/SaleRepository.cs
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
using Database.Models;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Database.Repository
|
||||||
|
{
|
||||||
|
public class SaleRepository
|
||||||
|
{
|
||||||
|
public SaleEntity New(int employeeId)
|
||||||
|
{
|
||||||
|
using PosDbContext context = new PosDbContext();
|
||||||
|
SaleEntity saleEntity = new SaleEntity();
|
||||||
|
saleEntity.Time = DateTime.Now;
|
||||||
|
saleEntity.EmployeeId = employeeId;
|
||||||
|
saleEntity.IsModified = true;
|
||||||
|
context.Sales.Add(saleEntity);
|
||||||
|
context.SaveChanges();
|
||||||
|
return saleEntity;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SaleLineEntity SaveSaleLine(SaleLineEntity entity)
|
||||||
|
{
|
||||||
|
using PosDbContext context = new PosDbContext();
|
||||||
|
context.SalesLines.Add(entity);
|
||||||
|
context.SaveChanges();
|
||||||
|
return entity;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<SaleLineEntity> GetSaleLineBySaleId(int saleId)
|
||||||
|
{
|
||||||
|
using PosDbContext context = new PosDbContext();
|
||||||
|
List<SaleLineEntity> saleLineEntities = context.SalesLines.Where(c => c.SaleId == saleId).ToList();
|
||||||
|
return saleLineEntities;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PaymentEntity SavePayment(PaymentEntity entity)
|
||||||
|
{
|
||||||
|
using PosDbContext context = new PosDbContext();
|
||||||
|
context.Payment.Add(entity);
|
||||||
|
context.SaveChanges();
|
||||||
|
return entity;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<PaymentEntity> GetPaymentBySaleId(int saleId)
|
||||||
|
{
|
||||||
|
using PosDbContext context = new PosDbContext();
|
||||||
|
List<PaymentEntity> paymentEntities = context.Payment.Where(c => c.SaleId == saleId).ToList();
|
||||||
|
return paymentEntities;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SaleEntity GetLatest()
|
||||||
|
{
|
||||||
|
using PosDbContext context = new PosDbContext();
|
||||||
|
SaleEntity saleEntity = context.Sales.OrderByDescending(c => c.Id).Take(1).First();
|
||||||
|
return saleEntity;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SaleEntity Get(int id)
|
||||||
|
{
|
||||||
|
using PosDbContext context = new PosDbContext();
|
||||||
|
SaleEntity saleEntity = context.Sales.Single(c => c.Id == id);
|
||||||
|
return saleEntity;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<SaleEntity> GetByDateRange(DateTime start, DateTime end)
|
||||||
|
{
|
||||||
|
using PosDbContext context = new PosDbContext();
|
||||||
|
List<SaleEntity> saleEntities = context.Sales.Where(c => c.Time.Date >= start.Date && c.Time.Date <= end.Date).OrderByDescending(c => c.Time).ToList();
|
||||||
|
return saleEntities;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<SaleEntity> GetByDateRange(DateTime start)
|
||||||
|
{
|
||||||
|
using PosDbContext context = new PosDbContext();
|
||||||
|
List<SaleEntity> saleEntities = context.Sales.Where(c => c.Time.Date == start.Date.Date).OrderByDescending(c => c.Time).ToList();
|
||||||
|
return saleEntities;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using EpsonPrinter.Model;
|
||||||
|
using EpsonPrinter.Services;
|
||||||
|
|
||||||
|
namespace EpsonPrinter.Controllers
|
||||||
|
{
|
||||||
|
[Route("api/[controller]")]
|
||||||
|
[ApiController]
|
||||||
|
public class PosPrinterController : ControllerBase
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// PrintReceipt receipt, so far only for all Epson Thermal Printers
|
||||||
|
/// </summary>
|
||||||
|
/// PrintStyle is:
|
||||||
|
/// None
|
||||||
|
/// FontB
|
||||||
|
/// Bold
|
||||||
|
/// DoubleHeight
|
||||||
|
/// DoubleWidth
|
||||||
|
/// Underline
|
||||||
|
/// There is support for any combination of PrintStyles
|
||||||
|
/// ----------------------------------------
|
||||||
|
///
|
||||||
|
///
|
||||||
|
/// <param name="receiptModel"></param>
|
||||||
|
[HttpPost]
|
||||||
|
[Route("Receipt")]
|
||||||
|
public void PrintReceipt([FromServices] EpsonPrintService epsonPrint, ReceiptModel receiptModel)
|
||||||
|
{
|
||||||
|
epsonPrint.PrintReceipt(receiptModel);
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPost]
|
||||||
|
[Route("SaleOfDay")]
|
||||||
|
public void PrintSaleOfDay([FromServices] EpsonPrintService epsonPrint, SaleOfDayModel saleOfDayModel)
|
||||||
|
{
|
||||||
|
epsonPrint.PrintSaleOfDay(saleOfDayModel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
|
||||||
|
namespace EpsonPrinter.Controllers
|
||||||
|
{
|
||||||
|
[Route("api/[controller]")]
|
||||||
|
[ApiController]
|
||||||
|
public class ValuesController : ControllerBase
|
||||||
|
{
|
||||||
|
[HttpGet]
|
||||||
|
[Route("HelloWorld")]
|
||||||
|
public string Get()
|
||||||
|
{
|
||||||
|
return "HelloWorld";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
PointOfSale/Pos.Ui/EpsonPrinter/ESC-POS/ESC-POS-.NET-master.zip
Normal file
BIN
PointOfSale/Pos.Ui/EpsonPrinter/ESC-POS/ESC-POS-.NET-master.zip
Normal file
Binary file not shown.
1
PointOfSale/Pos.Ui/EpsonPrinter/ESC-POS/ESC-POS-.NET-master/.gitattributes
vendored
Normal file
1
PointOfSale/Pos.Ui/EpsonPrinter/ESC-POS/ESC-POS-.NET-master/.gitattributes
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
* text=auto
|
||||||
12
PointOfSale/Pos.Ui/EpsonPrinter/ESC-POS/ESC-POS-.NET-master/.github/FUNDING.yml
vendored
Normal file
12
PointOfSale/Pos.Ui/EpsonPrinter/ESC-POS/ESC-POS-.NET-master/.github/FUNDING.yml
vendored
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
# These are supported funding model platforms
|
||||||
|
|
||||||
|
github: ['lukevp']
|
||||||
|
#patreon: # Replace with a single Patreon username
|
||||||
|
#open_collective: # Replace with a single Open Collective username
|
||||||
|
#ko_fi: # Replace with a single Ko-fi username
|
||||||
|
#tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
|
||||||
|
#community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
|
||||||
|
#liberapay: # Replace with a single Liberapay username
|
||||||
|
#issuehunt: # Replace with a single IssueHunt username
|
||||||
|
#otechie: # Replace with a single Otechie username
|
||||||
|
#custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
|
||||||
7
PointOfSale/Pos.Ui/EpsonPrinter/ESC-POS/ESC-POS-.NET-master/.gitignore
vendored
Normal file
7
PointOfSale/Pos.Ui/EpsonPrinter/ESC-POS/ESC-POS-.NET-master/.gitignore
vendored
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
.vs/
|
||||||
|
.idea/
|
||||||
|
**/obj/
|
||||||
|
**/bin/
|
||||||
|
push.ps1
|
||||||
|
/push.txt
|
||||||
|
/ESCPOS_NET/ESCPOS_NET.csproj.user
|
||||||
@@ -0,0 +1,74 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFramework>net5.0</TargetFramework>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="5.0.0" />
|
||||||
|
<PackageReference Include="Newtonsoft.Json" Version="12.0.1" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\ESCPOS_NET\ESCPOS_NET.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<None Update="abe-lincoln.png">
|
||||||
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
|
<None Update="images\abe-lincoln.png">
|
||||||
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
|
<None Update="images\kitten.jpg">
|
||||||
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
|
<None Update="images\pd-logo-100.png">
|
||||||
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
|
<None Update="images\pd-logo-200.png">
|
||||||
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
|
<None Update="images\pd-logo-300.bmp">
|
||||||
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
|
<None Update="images\pd-logo-300.gif">
|
||||||
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
|
<None Update="images\pd-logo-300.jpg">
|
||||||
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
|
<None Update="images\pd-logo-300.png">
|
||||||
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
|
<None Update="images\pd-logo-400.png">
|
||||||
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
|
<None Update="images\pd-logo-500.png">
|
||||||
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
|
<None Update="images\pd-logo-600.png">
|
||||||
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
|
<None Update="images\pd-logo.png">
|
||||||
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
|
<None Update="images\pd-logo.svg">
|
||||||
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
|
<None Update="images\Portal_Companion_Cube.jpg">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
|
<None Update="kitten.jpg">
|
||||||
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
|
<None Update="pd-logo.svg">
|
||||||
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
|
<None Update="test-files\output-juliogamasso.bin">
|
||||||
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
@@ -0,0 +1,267 @@
|
|||||||
|
using ESCPOS_NET.Emitters;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Linq;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
|
namespace ESCPOS_NET.ConsoleTest
|
||||||
|
{
|
||||||
|
internal class Program
|
||||||
|
{
|
||||||
|
private static BasePrinter printer;
|
||||||
|
private static ICommandEmitter e;
|
||||||
|
|
||||||
|
static void Main(string[] args)
|
||||||
|
{
|
||||||
|
|
||||||
|
Console.WriteLine("Welcome to the ESCPOS_NET Test Application!");
|
||||||
|
Console.Write("Would you like to see all debug messages? (y/n): ");
|
||||||
|
var response = Console.ReadLine().Trim().ToLowerInvariant();
|
||||||
|
var logLevel = LogLevel.Information;
|
||||||
|
if (response.Length >= 1 && response[0] == 'y')
|
||||||
|
{
|
||||||
|
Console.WriteLine("Debugging enabled!");
|
||||||
|
logLevel = LogLevel.Trace;
|
||||||
|
}
|
||||||
|
var factory = LoggerFactory.Create(b => b.AddConsole().SetMinimumLevel(logLevel));
|
||||||
|
var logger = factory.CreateLogger<Program>();
|
||||||
|
ESCPOS_NET.Logging.Logger = logger;
|
||||||
|
|
||||||
|
Console.WriteLine("1 ) Test Serial Port");
|
||||||
|
Console.WriteLine("2 ) Test Network Printer");
|
||||||
|
Console.Write("Choice: ");
|
||||||
|
string comPort = "";
|
||||||
|
string baudRate;
|
||||||
|
string ip;
|
||||||
|
string networkPort;
|
||||||
|
response = Console.ReadLine();
|
||||||
|
var valid = new List<string> { "1", "2" };
|
||||||
|
if (!valid.Contains(response))
|
||||||
|
{
|
||||||
|
response = "1";
|
||||||
|
}
|
||||||
|
|
||||||
|
int choice = int.Parse(response);
|
||||||
|
|
||||||
|
if (choice == 1)
|
||||||
|
{
|
||||||
|
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||||
|
{
|
||||||
|
while (!comPort.StartsWith("COM"))
|
||||||
|
{
|
||||||
|
Console.Write("COM Port (enter for default COM5): ");
|
||||||
|
comPort = Console.ReadLine();
|
||||||
|
if (string.IsNullOrWhiteSpace(comPort))
|
||||||
|
{
|
||||||
|
comPort = "COM5";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Console.Write("Baud Rate (enter for default 115200): ");
|
||||||
|
baudRate = Console.ReadLine();
|
||||||
|
if (string.IsNullOrWhiteSpace(baudRate))
|
||||||
|
{
|
||||||
|
baudRate = "115200";
|
||||||
|
}
|
||||||
|
printer = new SerialPrinter(portName: comPort, baudRate: 115200);
|
||||||
|
}
|
||||||
|
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
|
||||||
|
{
|
||||||
|
Console.Write("File / virtual com path (eg. /dev/usb/lp0): ");
|
||||||
|
comPort = Console.ReadLine();
|
||||||
|
if (string.IsNullOrWhiteSpace(comPort))
|
||||||
|
{
|
||||||
|
comPort = "/dev/usb/lp0";
|
||||||
|
}
|
||||||
|
printer = new FilePrinter(filePath: comPort, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (choice == 2)
|
||||||
|
{
|
||||||
|
Console.Write("IP Address (eg. 192.168.1.240): ");
|
||||||
|
ip = Console.ReadLine();
|
||||||
|
if (string.IsNullOrWhiteSpace(ip))
|
||||||
|
{
|
||||||
|
ip = "192.168.254.202";
|
||||||
|
}
|
||||||
|
Console.Write("TCP Port (enter for default 9100): ");
|
||||||
|
networkPort = Console.ReadLine();
|
||||||
|
if (string.IsNullOrWhiteSpace(networkPort))
|
||||||
|
{
|
||||||
|
networkPort = "9100";
|
||||||
|
}
|
||||||
|
printer = new NetworkPrinter(settings: new NetworkPrinterSettings() { ConnectionString = $"{ip}:{networkPort}" });
|
||||||
|
}
|
||||||
|
|
||||||
|
bool monitor = false;
|
||||||
|
Thread.Sleep(500);
|
||||||
|
Console.Write("Turn on Live Status Back Monitoring? (y/n): ");
|
||||||
|
response = Console.ReadLine().Trim().ToLowerInvariant();
|
||||||
|
if (response.Length >= 1 && response[0] == 'y')
|
||||||
|
{
|
||||||
|
monitor = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
e = new EPSON();
|
||||||
|
var testCases = new Dictionary<Option, string>()
|
||||||
|
{
|
||||||
|
{ Option.SingleLinePrinting, "Single Line Printing" },
|
||||||
|
{ Option.MultiLinePrinting, "Multi-line Printing" },
|
||||||
|
{ Option.LineSpacing, "Line Spacing" },
|
||||||
|
{ Option.BarcodeStyles, "Barcode Styles" },
|
||||||
|
{ Option.BarcodeTypes, "Barcode Types" },
|
||||||
|
{ Option.TwoDimensionCodes, "2D Codes" },
|
||||||
|
{ Option.TextStyles, "Text Styles" },
|
||||||
|
{ Option.FullReceipt, "Full Receipt" },
|
||||||
|
{ Option.CodePages, "Code Pages (Euro, Katakana, Etc)" },
|
||||||
|
{ Option.Images, "Images" },
|
||||||
|
{ Option.LegacyImages, "Legacy Images" },
|
||||||
|
{ Option.LargeByteArrays, "Large Byte Arrays" },
|
||||||
|
{ Option.CashDrawerPin2, "Cash Drawer Pin2" },
|
||||||
|
{ Option.CashDrawerPin5, "Cash Drawer Pin5" },
|
||||||
|
{ Option.Exit, "Exit" }
|
||||||
|
|
||||||
|
};
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
foreach (var item in testCases)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"{(int)item.Key} : {item.Value}");
|
||||||
|
}
|
||||||
|
Console.Write("Execute Test: ");
|
||||||
|
|
||||||
|
if (!int.TryParse(Console.ReadLine(), out choice) || !Enum.IsDefined(typeof(Option), choice))
|
||||||
|
{
|
||||||
|
Console.WriteLine("Invalid entry. Please try again.");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
var enumChoice = (Option)choice;
|
||||||
|
if (enumChoice == Option.Exit)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Console.Clear();
|
||||||
|
|
||||||
|
if (monitor)
|
||||||
|
{
|
||||||
|
printer.Write(e.Initialize());
|
||||||
|
printer.Write(e.Enable());
|
||||||
|
printer.Write(e.EnableAutomaticStatusBack());
|
||||||
|
}
|
||||||
|
Setup(monitor);
|
||||||
|
|
||||||
|
printer?.Write(e.PrintLine($"== [ Start {testCases[enumChoice]} ] =="));
|
||||||
|
|
||||||
|
switch (enumChoice)
|
||||||
|
{
|
||||||
|
case Option.SingleLinePrinting:
|
||||||
|
printer.Write(Tests.SingleLinePrinting(e));
|
||||||
|
break;
|
||||||
|
case Option.MultiLinePrinting:
|
||||||
|
printer.Write(Tests.MultiLinePrinting(e));
|
||||||
|
break;
|
||||||
|
case Option.LineSpacing:
|
||||||
|
printer.Write(Tests.LineSpacing(e));
|
||||||
|
break;
|
||||||
|
case Option.BarcodeStyles:
|
||||||
|
printer.Write(Tests.BarcodeStyles(e));
|
||||||
|
break;
|
||||||
|
case Option.BarcodeTypes:
|
||||||
|
printer.Write(Tests.BarcodeTypes(e));
|
||||||
|
break;
|
||||||
|
case Option.TwoDimensionCodes:
|
||||||
|
printer.Write(Tests.TwoDimensionCodes(e));
|
||||||
|
break;
|
||||||
|
case Option.TextStyles:
|
||||||
|
printer.Write(Tests.TextStyles(e));
|
||||||
|
break;
|
||||||
|
case Option.FullReceipt:
|
||||||
|
printer.Write(Tests.Receipt(e));
|
||||||
|
break;
|
||||||
|
case Option.Images:
|
||||||
|
printer.Write(Tests.Images(e, false));
|
||||||
|
break;
|
||||||
|
case Option.LegacyImages:
|
||||||
|
printer.Write(Tests.Images(e, true));
|
||||||
|
break;
|
||||||
|
case Option.LargeByteArrays:
|
||||||
|
try
|
||||||
|
{
|
||||||
|
printer.Write(Tests.TestLargeByteArrays(e));
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"Aborting print due to test failure. Exception: {e?.Message}, Stack Trace: {e?.GetBaseException()?.StackTrace}");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case Option.CashDrawerPin2:
|
||||||
|
printer.Write(Tests.CashDrawerOpenPin2(e));
|
||||||
|
break;
|
||||||
|
case Option.CashDrawerPin5:
|
||||||
|
printer.Write(Tests.CashDrawerOpenPin5(e));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Console.WriteLine("Invalid entry.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
Setup(monitor);
|
||||||
|
printer?.Write(e.PrintLine($"== [ End {testCases[enumChoice]} ] =="));
|
||||||
|
printer?.Write(e.PartialCutAfterFeed(5));
|
||||||
|
|
||||||
|
// TODO: also make an automatic runner that runs all tests (command line).
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum Option
|
||||||
|
{
|
||||||
|
SingleLinePrinting = 1,
|
||||||
|
MultiLinePrinting,
|
||||||
|
LineSpacing,
|
||||||
|
BarcodeStyles,
|
||||||
|
BarcodeTypes,
|
||||||
|
TwoDimensionCodes,
|
||||||
|
TextStyles,
|
||||||
|
FullReceipt,
|
||||||
|
CodePages,
|
||||||
|
Images,
|
||||||
|
LegacyImages,
|
||||||
|
LargeByteArrays,
|
||||||
|
CashDrawerPin2,
|
||||||
|
CashDrawerPin5,
|
||||||
|
Exit = 99
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void StatusChanged(object sender, EventArgs ps)
|
||||||
|
{
|
||||||
|
var status = (PrinterStatusEventArgs)ps;
|
||||||
|
if (status == null) { Console.WriteLine("Status was null - unable to read status from printer."); return; }
|
||||||
|
Console.WriteLine($"Printer Online Status: {status.IsPrinterOnline}");
|
||||||
|
Console.WriteLine(JsonConvert.SerializeObject(status));
|
||||||
|
}
|
||||||
|
private static bool _hasEnabledStatusMonitoring = false;
|
||||||
|
|
||||||
|
private static void Setup(bool enableStatusBackMonitoring)
|
||||||
|
{
|
||||||
|
if (printer != null)
|
||||||
|
{
|
||||||
|
// Only register status monitoring once.
|
||||||
|
if (!_hasEnabledStatusMonitoring)
|
||||||
|
{
|
||||||
|
printer.StatusChanged += StatusChanged;
|
||||||
|
_hasEnabledStatusMonitoring = true;
|
||||||
|
}
|
||||||
|
printer?.Write(e.Initialize());
|
||||||
|
printer?.Write(e.Enable());
|
||||||
|
if (enableStatusBackMonitoring)
|
||||||
|
{
|
||||||
|
printer.Write(e.EnableAutomaticStatusBack());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
using ESCPOS_NET.Emitters;
|
||||||
|
using ESCPOS_NET.Utilities;
|
||||||
|
|
||||||
|
namespace ESCPOS_NET.ConsoleTest
|
||||||
|
{
|
||||||
|
public static partial class Tests
|
||||||
|
{
|
||||||
|
private const string websiteString = "https://github.com/lukevp/ESC-POS-.NET/";
|
||||||
|
public static byte[][] TwoDimensionCodes(ICommandEmitter e) => new byte[][] {
|
||||||
|
e.PrintLine("PDF417:"),
|
||||||
|
e.Print2DCode(TwoDimensionCodeType.PDF417, websiteString),
|
||||||
|
e.PrintLine(),
|
||||||
|
|
||||||
|
e.PrintLine("PDF417 (TINY):"),
|
||||||
|
e.Print2DCode(TwoDimensionCodeType.PDF417, websiteString, Size2DCode.TINY),
|
||||||
|
e.PrintLine(),
|
||||||
|
|
||||||
|
e.PrintLine("PDF417 (LARGE):"),
|
||||||
|
e.Print2DCode(TwoDimensionCodeType.PDF417, websiteString, Size2DCode.LARGE),
|
||||||
|
e.PrintLine(),
|
||||||
|
|
||||||
|
e.PrintLine("QRCODE MODEL 1:"),
|
||||||
|
e.Print2DCode(TwoDimensionCodeType.QRCODE_MODEL1, websiteString),
|
||||||
|
e.PrintLine(),
|
||||||
|
|
||||||
|
e.PrintLine("QRCODE MODEL 2:"),
|
||||||
|
e.PrintQRCode(websiteString),
|
||||||
|
e.PrintLine(),
|
||||||
|
|
||||||
|
e.PrintLine("QRCODE MICRO:"),
|
||||||
|
e.Print2DCode(TwoDimensionCodeType.QRCODE_MICRO, "github.com/lukevp"),
|
||||||
|
e.PrintLine(),
|
||||||
|
|
||||||
|
e.PrintLine("QRCODE MODEL 1 (TINY):"),
|
||||||
|
e.Print2DCode(TwoDimensionCodeType.QRCODE_MODEL1, websiteString, Size2DCode.TINY),
|
||||||
|
e.PrintLine(),
|
||||||
|
|
||||||
|
e.PrintLine("QRCODE MODEL 1 (LARGE):"),
|
||||||
|
e.Print2DCode(TwoDimensionCodeType.QRCODE_MODEL1, websiteString, Size2DCode.LARGE),
|
||||||
|
e.PrintLine()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
using ESCPOS_NET.Emitters;
|
||||||
|
using ESCPOS_NET.Utilities;
|
||||||
|
|
||||||
|
namespace ESCPOS_NET.ConsoleTest
|
||||||
|
{
|
||||||
|
|
||||||
|
public static partial class Tests
|
||||||
|
{
|
||||||
|
public static byte[][] BarcodeStyles(ICommandEmitter e) => new byte[][] {
|
||||||
|
//TODO: test all widths and put bar in front in label
|
||||||
|
e.PrintLine("Thinnest Width:"),
|
||||||
|
e.SetBarcodeHeightInDots(300),
|
||||||
|
e.SetBarWidth(BarWidth.Thinnest),
|
||||||
|
e.PrintBarcode(BarcodeType.UPC_A, "012345678905"),
|
||||||
|
|
||||||
|
e.PrintLine("Thin Width:"),
|
||||||
|
e.SetBarcodeHeightInDots(300),
|
||||||
|
e.SetBarWidth(BarWidth.Thin),
|
||||||
|
e.PrintBarcode(BarcodeType.UPC_A, "012345678905"),
|
||||||
|
|
||||||
|
e.PrintLine("Default Width:"),
|
||||||
|
e.SetBarcodeHeightInDots(300),
|
||||||
|
e.SetBarWidth(BarWidth.Default),
|
||||||
|
e.PrintBarcode(BarcodeType.UPC_A, "012345678905"),
|
||||||
|
|
||||||
|
e.PrintLine("Thicker Width:"),
|
||||||
|
e.SetBarcodeHeightInDots(300),
|
||||||
|
e.SetBarWidth(BarWidth.Thick),
|
||||||
|
e.PrintBarcode(BarcodeType.UPC_A, "012345678905"),
|
||||||
|
|
||||||
|
e.PrintLine("Thickest Width:"),
|
||||||
|
e.SetBarcodeHeightInDots(300),
|
||||||
|
e.SetBarWidth(BarWidth.Thickest),
|
||||||
|
e.PrintBarcode(BarcodeType.UPC_A, "012345678905"),
|
||||||
|
|
||||||
|
|
||||||
|
e.PrintLine("Short (50 dots):"),
|
||||||
|
e.SetBarcodeHeightInDots(50),
|
||||||
|
e.SetBarWidth(BarWidth.Default),
|
||||||
|
e.PrintBarcode(BarcodeType.UPC_A, "012345678905"),
|
||||||
|
|
||||||
|
e.PrintLine("Tall (255 dots):"),
|
||||||
|
e.SetBarcodeHeightInDots(255),
|
||||||
|
e.PrintBarcode(BarcodeType.UPC_A, "012345678905"),
|
||||||
|
|
||||||
|
e.PrintLine("Label Above:"),
|
||||||
|
e.SetBarcodeHeightInDots(50),
|
||||||
|
e.SetBarLabelPosition(BarLabelPrintPosition.Above),
|
||||||
|
e.PrintBarcode(BarcodeType.UPC_A, "012345678905"),
|
||||||
|
|
||||||
|
e.PrintLine("Label Above and Below:"),
|
||||||
|
e.SetBarLabelPosition(BarLabelPrintPosition.Both),
|
||||||
|
e.PrintBarcode(BarcodeType.UPC_A, "012345678905"),
|
||||||
|
|
||||||
|
e.PrintLine("Label Below:"),
|
||||||
|
e.SetBarLabelPosition(BarLabelPrintPosition.Below),
|
||||||
|
e.PrintBarcode(BarcodeType.UPC_A, "012345678905"),
|
||||||
|
|
||||||
|
e.PrintLine("Font B Label Below:"),
|
||||||
|
e.SetBarLabelFontB(true),
|
||||||
|
e.PrintBarcode(BarcodeType.UPC_A, "012345678905")
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user