GithubHelp home page GithubHelp logo

erpnet / erpnet.fp Goto Github PK

View Code? Open in Web Editor NEW
105.0 35.0 61.0 443.16 MB

ErpNet.FP is a light-weight cross-platform Http server facilitating printing to fiscal printers through simple JSON Api.

License: BSD Zero Clause License

C# 92.76% HTML 1.26% JavaScript 5.15% XSLT 0.51% Shell 0.32%
fiscal printer driver erpnet protocol json-api multiplatform http-server net-core-3 net-standard-2

erpnet.fp's Introduction

ErpNet.FP

ErpNet.FP is a light-weight multi-platform Http server facilitating printing to fiscal printers through simple JSON Api. The library provides methods to detect, get status, print receipts, reports and other documents to fiscal printers.

The ErpNet.FP http server provides a REST API with JSON input/output, which prints documents transactionally and returns result status.

The http server receives input through the REST API and uses different transports to communicate with the fiscal printers. The transports include:

  • COM serial connection
  • Bluetooth connection through mapping to COM port
  • TCP/IP
  • etc.

Shortcut to Download

The Net.FP Protocol

All communication with the ErpNet.FP print server is based on the Net.FP (Net Fiscal Protocol).

Requests

The print server accepts documents for printing, using JSON based protocol. For example, this would print the specified receipt to dt517985, which is the printerId of one of the detected printers, listed with GET /printers (see below for printerId explanation):

POST /printers/dt517985/receipt

{
  "uniqueSaleNumber": "DT279013-0001-0000001",
  "items": [
    {
      "text": "Cheese",
      "quantity": 1,
      "unitPrice": 12,
      "taxGroup": 2
    },
    {
      "type": "comment",
      "text": "Additional comment to the cheese..."
    },
    {
      "text": "Milk",
      "quantity": 2,
      "unitPrice": 10,
      "taxGroup": 2,
      "priceModifierValue": 10,
      "priceModifierType": "discount-percent"
    },
    {
      "type": "footer-comment",
      "text": "YOU ARE WELCOME!"
    }
  ],
  "payments": [
    {
      "amount": 30,
      "paymentType": "cash"
    }
  ]
}

For More Information

For more information, see the full documentation of the protocol.

Response - Interpreting The Results

The most important result is the "ok" field. It contains "true" when the POST operation was successful, otherwise - "false". If there was error, "ok" would be "false".

If "ok"="false", it is guaranteed, that at least one message of type "error" would be present.

The error and warning messages have standardized codes across all manufacturers. The standard error and warning codes are listed in the Error and Warning Codes file.

The standard error codes are a subset of all manufacturer codes and flags. In some cases, the specific manufacturer codes, flags and messages could contain more detailed information. The manufacturer code, when available, is contained in the "originalCode" field. The problem with using the manufacturer codes is that they are different for each manufacturer. For some manufacturers they are not even present (there might be just some status flags). The manufacturer codes can even change between revisions of printers of the same manufacturer. The standardized error and warning codes are guaranteed to be the same across all manufacturers and printer versions. Messages with "type": "info", have no codes, because they cannot be standardized.

Example Return JSON (No Problems) after printing receipt:

{
  "ok": "true",
  "messages": [
    {
      "type": "info",
      "text": "Serial number and number of FM are set"
    },
    {
      "type": "info",
      "text": "FM is formatted"
    }
  ],
  "receiptNumber": "0000085",
  "receiptDateTime": "2019-05-17T13:55:18",
  "receiptAmount": 30,
  "fiscalMemorySerialNumber": "02517985"
}

Example Return JSON (Warning) while getting the status:

{
  "ok": "true",
  "messages": [
    {
      "type": "warning",
      "code": "W201",
      "text": "The fiscal memory almost full"
    },
    {
      "type": "info",
      "text": "Serial number and number of FM are set"
    },
    {
      "type": "info",
      "text": "FM is formatted"
    }
  ],
  "deviceDateTime": "2019-05-10T15:50:00"
}

Example Return JSON (Error):

{
  "ok": "false",
  "messages": [
    {
      "type": "error",
      "code": "E201",
      "text": "The fiscal memory is full"
    },
    {
      "type": "info",
      "text": "Serial number and number of FM are set"
    },
    {
      "type": "info",
      "text": "FM is formatted"
    }
  ]
}

Download

Eager to try? You can list and download the binaries for ErpNet.FP.Server:

Windows 32/64 Service Installer (.MSI) ** New **

Download: Installer for Windows 32/64

The Windows installer setups or updates the ErpNet.FP Fiscal Print Server on a Windows 32 or 64 bit OS. The installer unpacks and installs a Windows service, called "ErpNet.FP". There is no UI, but when the service is running in the default configuration, you can browse the Admin page at http://localhost:8001.

Windows 32/64 bit, folder install

Download 32 bit (x86): win-x86.zip - Windows 32 bit

Download 64 bit (x64): win-x64.zip - Windows 64 bit

Download and unzip the file in a folder. Inside the folder you will find executable file: ErpNet.FP.Server.exe. To start the printing service, run ErpNet.FP.Server.exe, or register the executable as a Windows service. When the service is running in the default configuration, you can browse the Admin page at http://localhost:8001.

OSX 10.10 and up, 64 bit folder install

Download 64 bit - osx-x64.zip - macOS - You can download and unzip the server in a folder.

Inside the unzipped folder, run it from console/terminal with:

./ErpNet.FP.Server

When the service is running in the default configuration, you can browse the Admin page at http://localhost:8001.

Linux 64 bit, folder install

Download 64 bit - linux-x64.zip - Linux x64 - You can download and unzip the server.

Because of the serial ports default permissions, run it from sudoer, with sudo, or in the root user context. For convenience, create a systemd service config file, get more info how to do it here Systemd: Service File Examples. The other way is to run it from non-root user, but that user should have permissions to read and write to serial ports. When the service is running in the default configuration, you can browse the Admin page at http://localhost:8001.

Linux-Arm 64 bit, folder install

Download 64 bit - linux-arm.zip - Linux Arm - You can download and unzip the server.

This version is compatible with Raspberry PI OS, Raspbian, and 64 bit Arm devices like Raspberry PI 3B+, Raspberry PI 2 and up. Because of the serial ports default permissions, run it from sudoer, with sudo, or in the root user context. For convenience, create a systemd service config file, get more info how to do it here Systemd - Raspberry Pi Documentation. The other way is to run it from non-root user, but that user should have permissions to read and write to serial ports. When the service is running in the default configuration, you can browse the Admin page at http://localhost:8001.

Important: The requirement for running ARM CPUs is to support at least the vfpv4d32 floating point feature. This is why we prefer to support only 64 bit CPUs, because they support that feature and more... For reference see: Issue 17043 at dotnet/coreclr.

Debug information

For debugging purposes, there is a link to debug.log and it's folder in the Admin page. It contains debug information for every event that occured while using the service.

Server Configuration

The server configuration options are located in a file, called "appsettings.json". For more information, see Configuration. It is recommended that you use the Admin page, or through /service API to edit the settings in this file rather than edit it directly.

Fiscal Printer Setup

Most fiscal printers or cash register should be in "Fiscal Printer" mode in order to accept commands from the PC through the serial interface. Refer to your printer manual how to setup the fiscal printer mode.

The following non-comprehensive article contains the setup procedure for some fiscal printers:

Concepts

Printer Id

Each printer is identified by its printerId. Although the library consumer does not need to know the exact specifics of the algorithm for generating the printerId, they are provided here for completeness:

  1. For locally connected printers, the printerId is the printer serial number. For example: "dy448967"

  2. If a local printer is connected through multiple transports (for example: both COM and BT), the id for each next transport connection is assigned a consecutive number. For example: "dy448967_1" Note: The algorithm runs always in the same order. Unless transports are changed, the id would remain constant. However, it is advised to always use the default, non-numeric id.

  3. For network printers, the printerId is provided in the configuration file. For example: "FP_Room1"

Printer Uri

When a printer is detected, the http server saves something, called printer Uri. The Uri contains the connection information to connect to the printer. It contains details about printer driver, transport and path to the printer. It is similar to the connection string pattern. Example Uris:

  • bg.dy.isl.com://COM5
  • bg.dy.isl.com://COM3
  • bg.dt.x.isl.com://COM21
  • bg.zk.zfp.http://fp5.mycompany.com
  • bg.dt.p.isl.tcp://192.168.1.77:9100
  • etc.

The printer Uri is currently used only internally in the http server. Still, it is exposed as part of the device info. In the future, there might be methods to use the printers through their Uri.

Supported devices and operating systems

Currently, the http server is available for:

  • Windows 32/64 bit
  • macOS 10.10 and up
  • Linux x64
  • Linux Arm

The library supports printers from the following manufacturers:

If you want your device to be supported, please contact us, and we will try our best to help you!

Tested on

  • Datecs DP-25, firmware: 263453 08Nov18 131, protocol: bg.dt.c.isl.com
  • Datecs WP-50, firmware: 261403 08Nov18 1050, protocol: bg.dt.c.isl.com
  • Datecs FP-2000, firmware: 1.00BG 23NOV18 1000, protocols: bg.dt.p.isl.com, bg.dt.p.isl.tcp
  • Datecs FP-700X, firmware: 266207 29Jan19 1634, protocols: bg.dt.x.isl.com, bg.dt.x.isl.tcp
  • Daisy CompactM, firmware: ONL-4.01BG, protocol: bg.dy.isl.com
  • Daisy CompactM, firmware: ONL01-4.01BG, protocol: bg.dy.isl.com
  • Eltrade A1, firmware: KL5101.1811.0.3 15Nov18 15:49, protocol: bg.ed.isl.com
  • Tremol FP01-KL-V2, firmware: 99C4, protocol: bg.zk.v2.zfp.com
  • Tremol M20, firmware: Ver. 1.01 TRA20 C.S. 25411, protocol: bg.zk.zfp.com
  • Incotex 300SM KL-Q, firmware: 2.11 Jan 22 2019 14:00, protocol: bg.in.isl.com
  • ISL5011S-KL, firmware: BG R1 21.01.201948, protocol: bg.is.icp.com

Supported protocols and devices

  • bg.dt.c.isl - Datecs WP-50, Datecs DP-05, Datecs DP-05B, Datecs DP-05C, Datecs DP-25, Datecs DP-35, Datecs DP-150, Datecs DP-15

  • bg.dt.p.isl - Datecs FP-650, Datecs FP-800, Datecs FP-2000, Datecs FMP-10, Datecs SK1-21F, Datecs SK1-31F

  • bg.dt.x.isl - Datecs DP-25X, Datecs FMP-350X, Datecs FP-700X, Datecs WP-500X, Datecs FMP-55X, Datecs WP-50X, Datecs FP-700X, Datecs DP-150X, Datecs WP-25X, Datecs FP-700XE

  • bg.zk.zfp - Tremol A19Plus, Tremol S21, Tremol M23, Tremol M20, Tremol FP15, Tremol SB, Tremol S25, Tremol FP24

  • bg.zk.v2.zfp - Tremol Z-KL-V2, Tremol ZM-KL-V2, Tremol ZS-KL-V2, Tremol FP01-KL V2, Tremol FP05-KL V2, Tremol M-KL-V2, Tremol S-KL-V2, Tremol FP15 KL V2, Tremol FP03-KL V2, Tremol FP07-KL V2, Tremol FP01, Tremol FP21

  • bg.ed.isl - Eltrade A1 KL, Eltrade A1 KL, Eltrade A3 KL, Eltrade B1 KL, Eltrade PRP 250F KL, Eltrade A6 KL, Eltrade B3 KL, EPSON TM - T810F KL модел 01, EPSON TM - T81F KL модел 03, ELTRADE PRP 250F KL

  • bg.dy.isl - Daisy Compact S, Daisy Compact M, Daisy eXpert SX 01, Daisy eXpert SX, Daisy Compact M 02, Daisy Compact S 01, Daisy Perfect M 01, Daisy MICRO C 01, Daisy Compact M 01, Daisy eXpert 01, Daisy Perfect S 01, Daisy FX 1300, Daisy FX 1200C, Daisy Perfect SA, Daisy FX 21 01

  • bg.in.isl - Incotex 133 KL-Q, Incotex 181 KL-Q, Incotex 777, Incotex 300SM KL-Q, Incotex 300S KL-Q

  • bg.is.icp - ISL5011S-KL

  • Didn't find your device on the list? Please, create an issue here in the project and we will check whether we can support it with the current set of protocols or we need to implement a new one.

Default passwords we use in the library.

This is a list of default credentials we use in the library, when there is no exclusive override of the values in the Json fields "operator" and "operatorPassword", while you make a Json requests to the fiscal device.

  • bg.dt.c.isl - "operator" : "1", "operatorPassword": "1"
  • bg.dt.p.isl - "operator" : "1", "operatorPassword": "0000"
  • bg.dt.x.isl - "operator" : "1", "operatorPassword": "0000"
  • bg.zk.zfp - "operator" : "1", "operatorPassword": "0000"
  • bg.zk.v2.zfp - "operator" : "1", "operatorPassword": "0000"
  • bg.ed.isl - "operator" : "1", "operatorPassword": N/A
  • bg.dy.isl - For receipts: "operator" : "1", "operatorPassword": "1", and for reversalReceipts: "operator" : "20", "operatorPassword": "9999"
  • bg.in.isl - "operator" : "1", "operatorPassword": "1"
  • bg.is.icp - "operator" : "1", "operatorPassword": N/A

Source Code

To compile and run the source code, you will need .Net 7.0 SDK installed.

To build the binaries into Published folder and .zip files into Output folder, just write this line in the console, while you are in the ErpNet.FP folder:

dotnet msbuild output.xml

If you are under Windows, you can install Wix toolset - Wix 3.11 and you will be able to build ErpNet.FP.Setup and to get the Windows MSI setup file into the Output folder.

As IDE for Windows, you can use Visual Studio 2022. For macOS, you can use Visual Studio for Mac 8.3. For Linux, or as alternative for Windows and macOs, you can use Visual Studio Code.

Support

ErpNet.FP is free, open and works great. Most people use ErpNet.FP without any kind of support.

Free support for ErpNet.FP is available on the https://www.facebook.com/groups/BgBusinessDev/. This group is monitored by a community of experts, including the core ErpNet.FP development team, who are able to resolve your problems with ErpNet.FP that you are likely to have. The main language of this group is Bulgarian, but you can post your questions in English.

License

"BSD Zero Clause License", see LICENSE.txt

Contributing

See our Contributing document and our Code of Conduct document, to learn how to help us.

erpnet.fp's People

Contributors

de1facto avatar dilyanrusev avatar drjeckyll avatar g-vvv avatar i-argentinski avatar kostadinko avatar moxata avatar o-ivanov avatar p-kostov avatar rosen4o avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

erpnet.fp's Issues

"discount-amount" error on protocol bg.dt.c.isl.com

Describe the bug
Syntax error while print "discount-amount" on protocol bg.dt.c.isl.com
Seems wrong prefix "$" before the amount. The protocol reference points ";"

Executed command:
Request(31): 'Артикул Б1.00*1$-0.03'

Protocol refence:
31h (49) [<L1>][<Lf><L2>]<Tab><TaxCd><[Sign]Price>[*<Qwan>][,Perc|;Abs]

Describe the device(s) you are using
Datecs DP-150

Screenshots

Request(31): 'Артикул	Б1.00*1$-0.03'
>>>1 39 29 31 C0 F0 F2 E8 EA F3 EB 9 C1 31 2E 30 30 2A 31 24 2D 30 2E 30 33 5 30 39 3E 30 3 
<<<16 
<<<1 2B 29 31 4 A1 A0 88 80 84 82 5 30 33 3D 3D 3 

Skip the "code" field in the return JSON when it has no value

Currently, messages/code is included in the return JSON even if it has no value.

For example:

{
	"ok": "false",
	"messages": [
		{ 
			"type": "error",
			"code": "E201",
			"text": "The fiscal memory is full"
		},
		{
			"type": "info",
			"code": "",
			"text": "Serial number and number of FM are set"
		},
		{
			"type": "info",
			"code": "",
			"text": "FM is formatted"
		}
	]
}

The "code" field for the 2nd and the 3rd messages is unnecessary and even wrong. The code really has no value. It is neither "" nor "null".

Just skip the code if it has no value.

The above JSON should become:

{
	"ok": "false",
	"messages": [
		{ 
			"type": "error",
			"code": "E201",
			"text": "The fiscal memory is full"
		},
		{
			"type": "info",
			"text": "Serial number and number of FM are set"
		},
		{
			"type": "info",
			"text": "FM is formatted"
		}
	]
}

Auto save to config detected printers and other config changes

Auto save to config file appsettings.json all detected printers, for future use. Also will set AutoDetect = false, when there is at least one working printer available. This is because in the default case, for the user auto detection will be valuable only in that case. Of course is possible to force auto detection with AutoDetect = true in the config file. It is possible to have aliases, i.e. different PrinterId with the same Uri in the config file appsettings.json. There is new section in the appsettings.json, "ErpNet.FP" to be compatible with others, like "Kestrel", etc.. AutoDetect and Printers sub sections are under "ErpNet.FP" section now.

Simplify the resource names

POST /printreceipt => POST /receipt
POST /printxxx => POST /xxx
...
POST /setdatetime => POST /datetime

The idea is that we drop the verb from the resource name. The HTTP verb is now the verb.

Include requests and responses in debug.log

In order to be better able to handle support requests in the future, the debug.log file should contain data about requests and responses. To be more precise - the full text of each request and each response should be dumped in debug.log.

The text representation should be clear of any escape symbols. The idea is that sometimes the problems with malformed requests are exactly bad escaping (for example, bad escaping of the double quotes (") in a JSON request).

Cash amount and Timestamp in Info Method

A few recommendations
It's convenient to return in info method (which I use like an a ping or init) current cash because Cash Out, sometimes Storno, Operator Name change (of Datecs) and probably others will fail if application does not catch cash availability. Also current time of ECR will be valuable in info, so application can try to fix wrong calendar.
I found that devices fails if item price is zero (gift) and in my application I replace "Sell" method with a "print comment" if price is zero, but this behavior is constant and could be catch in the communication layer to avoid additional logic in application.
And last, because subtotal have to be positive in every moment some negative items should be shifted at the end if current amount goes negative.

E403 - priceModifierValue - should be positive number.

Testing with the following curl command results an error - i dont have "priceModifierValue" in my command.

curl --location --request POST "http://192.168.1.149:8001/printers/tcp/receipt" \
  --header "Content-Type: application/json" \
  --data "{
	\"uniqueSaleNumber\": \"DT279013-DD01-0000001\",
	\"items\" : 
	[
		{
			\"text\": \"Cheese\",
			\"quantity\": 1,
			\"unitPrice\": 12,
			\"taxGroup\": 2
		}
	]
}"

the result is

"ok": false,
	"messages": [{
		"type": "error",
		"code": "E403",
		"text": "Item 1: \"priceModifierValue\" should be positive number. You can avoid setting priceModifier if you do not want price modification"
	}, {
		"type": "error",
		"code": "E403",
		"text": "Item 1: \"priceModifierValue\" should'nt be \"none\" or empty. You can avoid setting priceModifier if you do not want price modification"

Using version - ver.1.0.2006.1330

Get a unique workplace identifier

Get a unique workplace identifier on the device where the ErpNet.FP server is running.
By government requirements for workplaces, from annex 29 points 5, 8, 18, 18.1, 18.9.

It can also help for control fiscal devices usage - set defaults or restrict, when more than one available for a workplace.

For softwares without locally installed modules, it will eliminate the need to install an extra server to obtain workplace id.

Identifier may be a bios serial, drive serial, ethernet adapter or other unique identifier.
Response may be a hash, to keep a fixed length.

Example Request
GET: /deviceuid

Example Response

{
	"deviceuid": "2C290D367A8020BF6F75F5AB4B0E8F30"
}

Get the status of the last fiscal transaction


name: Feature request
about: Suggest an idea for this project
title: 'Get the status of the last fiscal transaction'
labels: 'enhancement'
assignees: ''


Is your feature request related to a problem? Please describe.
Frequently, there is a loss of connection with the software during printing. The ability to check the status of the last fiscal transaction any time after, will help to decide how to complete the sale.

Describe the solution you'd like
To have command which return the info of the last transaction. For example:
GET: /printers/dt525860/lasttransactionstatus

Describe alternatives you've considered
This is partially accomplished with asynchronous tasks, but it can not cover all cases.

Unable to print receipts due to encoding issue

Describe the bug
Wrong encoding in the committed file: BgIslFiscalPrinter.cs - the file is saved with ANSI encoding which replaces the Cyrillic characters from the tax group with unreadable ones. This subsequently leads to the inability to process the POST request, returning a syntax error.
Please commit the file again with UTF-8 encoding.

Describe the device(s) you are using
Daisy Perfect S

How To Reproduce
Just check the content of the committed file:

switch (taxGroup) { case TaxGroup.TaxGroup1: return "À"; case TaxGroup.TaxGroup2: return "Á"; case TaxGroup.TaxGroup3: return "Â"; case TaxGroup.TaxGroup4: return "Ã"; case TaxGroup.TaxGroup5: return "Ä"; case TaxGroup.TaxGroup6: return "Å"; case TaxGroup.TaxGroup7: return "Æ"; case TaxGroup.TaxGroup8: return "Ç"; default: throw new StandardizedStatusMessageException($"Tax group {taxGroup} unsupported", "E411"); }

Expected behavior
Unable to print receipts.

DP-150

Hi,
I'm trying to test with Datecs DP-150 but it can not be detected.
FPInit detects it and test fiscal receipts can be printed, so it is correctly attached/setup.
Can you please help out.
Thanks

DATECS FP-800 over tcp failed

Hi.
I have problem connecting to datecs fp-800 printer over tcp.

This is the console log.

info: ErpNet.FP.Server.Program[0]
Starting the service...
info: ErpNet.FP.Server.Contexts.PrintersControllerContext[0]
Detecting configured printers...
info: ErpNet.FP.Server.Contexts.PrintersControllerContext[0]
Trying dt315421: bg.dt.p.isl.com://COM1, OK
info: ErpNet.FP.Server.Contexts.PrintersControllerContext[0]
Trying dt315421_1: bg.dt.p.isl.tcp://192.168.1.94, failed
info: ErpNet.FP.Server.Contexts.PrintersControllerContext[0]
Detecting done. Found 1 available printer(s).
Hosting environment: Production
Content root path: c:\Users\loboda\Downloads\win-x64
infoNow listening on: http://0.0.0.0:8001
Application started. Press Ctrl+C to shut down.
: ErpNet.FP.Server.Services.KeepAliveHostedService[0]
Keep Alive Background Service is starting.
info: ErpNet.FP.Server.Services.KeepAliveHostedService[0]
Keep Alive Background Service running...
info: ErpNet.FP.Server.Services.KeepAliveHostedService[0]
Keep Alive Background Service done.
info: ErpNet.FP.Server.Services.KeepAliveHostedService[0]
Keep Alive Background Service running...
info: ErpNet.FP.Server.Services.KeepAliveHostedService[0]
Keep Alive Background Service done.
info: ErpNet.FP.Server.Services.KeepAliveHostedService[0]
Keep Alive Background Service running...
info: ErpNet.FP.Server.Services.KeepAliveHostedService[0]
Keep Alive Background Service done.
info: ErpNet.FP.Server.Services.KeepAliveHostedService[0]
Keep Alive Background Service running...
info: ErpNet.FP.Server.Services.KeepAliveHostedService[0]
Keep Alive Background Service done.

No problem when using com1 port.

No problem using other software with the fiscal printer (not at the same time) so no network problem.

this is my appsettings.json

{
"Logging": {
"LogLevel": {
"Default": "Information"
}
},
"ErpNet.FP": {
"AutoDetect": false,
"ServerId": "aR5rIm76EESRhUmxVqTLjA",
"Printers": {
"dt315421": {
"Uri": "bg.dt.p.isl.com://COM1"
},
"dt315421_1": {
"Uri": "bg.dt.p.isl.tcp://192.168.1.94"
}
}
},
"Kestrel": {
"EndPoints": {
"Http": {
"Url": "http://0.0.0.0:8001"
}
},
"Limits": {
"MaxConcurrentConnections": 100,
"MaxConcurrentUpgradedConnections": 100,
"MaxRequestBodySize": 20480,
"MaxRequestHeaderCount": 50
}
}
}

I hear the beep of tcp connection but the status is failed.

I am attaching wireshark capture file of the transmitted packets.

fp800.zip

Keep printer time synced with NTP

Keep the printer synchronized with EU NTP time server.

The service should regularly check (or on each PrintReceipt) NTP server and if the printer current time is out of sync - set it.

If the difference between the NTP and the FP is more than 30 sec - then set the printer time.

The NTP server pool should default to some EU NTP server pool. But the address of the NTP server should be configurable through the config file.

Payment error on async mode cause infinitely running task


name: Bug report
about: Create a report to help us improve
title: 'Payment error on async mode cause infinitely running task'
labels: bug
assignees: ''


Describe the bug
When try print error receipt, print stopping before payment row and task stay "running" infinitely. The printing stuck to items row.
When try print non error receipt after, his task receive status finished and finalize stucked printing with cancelation. But the first receipt task continue return "running" infinity.

The same receipt with payment "check" in synchronous mode is finalized correctly.

Describe the device(s) you are using
Datecs DP-150 in non-fiscal mode
{"uri":"bg.dt.c.isl.com://COM7","serialNumber":"DT746009","fiscalMemorySerialNumber":"02746009","company":"Datecs","model":"DP-150","firmwareVersion":"265403 08Nov18 1050","itemTextMaxLength":22,"commentTextMaxLength":42,"operatorPasswordMaxLength":8}

How To Reproduce

  1. Print receipt with payment "check", to force error E404 not allowed in current mode.
  2. Task state stay "running" for 30 minutes and continue. The receipt stuck printed to items rows.
  3. Print another receipt with payment "cash"
  4. The second receipt task_id return status finished, with error E404. The printer finalize stucked print with cancelation.
  5. Task first receipt task continue to return "running"
    Steps are visible in attached debug.log

Expected behavior
In step 2. task should return state finished with error E404.

Screenshots
20190602_143031
debug.log.1.zip

Additional context

Customization of fiscal bon

View of bon
Would be great if all settings of OpenFiscalBon are presented into input JSON. For example Tremol's OptionReceiptFormat and OptionPrintVAT, for Datecs TillNumber etc.

Often I print additional info for specific articles (as serial numbers, contract number etc.), so in my subsys I have PrintBefore and PrintAfter in Items object. Additionally in PrintBefore and PrintAfter sometimes I print barcodes too.

On error, result is "ok":true.

When message of type error exists, the print is canceled corectlly, but result "ok" is set to true.
Is not it expected to be false?

{
   "taskStatus":"finished",
   "result":{
      "receiptNumber":"",
      "receiptDateTime":"0001-01-01T00:00:00",
      "receiptAmount":0.0,
      "fiscalMemorySerialNumber":"02746009",
      "ok":true,
      "messages":[
         {
            "type":"error",
            "code":"E406",
            "text":"Payment type Check unsupported"
         },
         {
            "type":"info",
            "code":"",
            "text":"Error occured while printing receipt items"
         }
      ]
   }
}}

Support async printing and queueing

The idea is that each printing request will be enqueued in a queue.

(1) /printreceipt
will:

  • enqueue the printing task.
  • wait up to 29 secs for the queued task.
  • return the usual PrintInfo result

(2) /printreceipt?asynctimeout=15000
will:

  • enqueue the printing task.
  • wait up to 15000 ms.
  • If the print task is finished within 15000 ms - return the usual PrintInfo result
  • if the print job took more than 15000 ms - return TaskId result.

(3) /printreceipt?asynctimeout=0
will:

  • enqueue the printing task.
  • return TaskId result.

Show printer address in admin web UI

The idea is to display the full printer address in the admin UI. This will facilitate external applications, which require the users to configure the printer address.

The printer address should be displayed when we open the printer details in the admin UI.

For example, a printer address is:
https://mycomputer:8001/printers/dt1234

The "https://mycomputer:8001" part should be taken from the URL of the web request which requested the admin web UI.

For example, the user requested the admin UI with:
https://mycomputer:8001/admin

This means that he "sees" the print server as "https://mycomputer:8001". So, we will use this to construct the full printer address.

Support configurable logging

{
  "Logging": {
    "LogLevel": {
      "Default": "Warning"
    }
  },
  "Printers": {
    "prn1": { "Uri": "bg.zk.zfp.com://COM1" },
    "prn2": { "Uri": "bg.dt.p.isl.tcp://192.168.1.100:4999"  }
  },
  "AutoDetect": true,
  "Kestrel": {
    "EndPoints": { 
      "Http": {
        "Url": "http://0.0.0.0:8001"
      }
    }
  }
}

Selection of multi platform .Net Core serial port library

We must select multi platform .net core serial port library, which will be used as standard underlying communication with Fiscal Printers and Devices. This is team task, so I assigned this task to all of us. Please consider that there are not so many packed as NuGet packages, as well as we must select the library with minimal dependencies and maximum portability.
Without this library we will be forced to use only Microsoft Windows System.IO.Ports, which is not supported in .Net Core, and stick only with Windows :(

Print X/Z report from admin page

The idea is to facilitate the users/developers. The applications will no longer need to integrate functionality for printing X/Z reports. This will be doable from within the print server web interface.

From within the admin web page, put
Print X Report
Print Z Report
buttons.

These button should initiate the printing of X and Z reports.

Admin controller a.k.a. /admin

Admin controller will provide feedback and control abilities for third party apps over ErpNet.FP, via Kestrel http. ErpNet.FP.Win.Manager for example will use it for feedback and control over ErpNet.FP.Win.

Create Admin panel with MQTT activation

The admin panel would allow remote administration (making changes to the config file, etc.) of the print server.

Currrently, the admin panel would be a web page. In the future, Api access should also be allowed.

All admin access (web page AND api access) should be secured with a simple "Admin Secret". The admin secret is a password, stored in the config file.

NOTE: If the admin password is NOT set, ALL admin access is DISABLED. E.g., there SHOULD be an admin password in order to access the admin part.

(1) Admin password
The password would be stored in the ErpNet.FP section, under the name "AdminPassword". It would be plain-text "secret" text.

NOTE: Obviously, this is not the highest level of security, but it is secure enough for remote access.

(2) MQTT secret
The MQTT secret is used to create topic names for the MQTT communication. It is stored in the config file, in the ErpNet.FP section, under the name "MqttSecret".

(3) Functions of the admin web page
Location: /admin/
Login: Each access of any admin page should require a login, requiring the user to type the admin password.
Functions:

  • Button "Set Admin Password" - should allow the user to change the admin password.
  • Button "Enable/Disable MQTT"
  • If there is no MqttSecret, a new one is generated
  • Upon MQTT activation (or just always), a JavaScript snippet should be displayed, showing the necessary JavaScript code to access the printing functions.
    NOTE: The snippet should be with the MQTT secret already integrated into it.

Implement Invoice, Credit and Debit notice functionality

First of all I am very grateful for the existence of this product and big congrats to all developers. The software is very useful.

Here is the future request I am thinking about:

Is your feature request related to a problem? Please describe.
A lot of companies print the invoice in the fiscal bon. For example Tehnomarket in Bulgaria.

Describe the solution you'd like
I would expect an API endpoints where a request can make the fiscal printer to output a fiscal bon with invoice, credit or debit notice details on it.

Describe alternatives you've considered
The only alternative is to print an invoice or the other types of documents standalone and attach the fiscal bon to the document.

Config should support specifying printers and auto detect

{
  "Logging": {
    "LogLevel": {
      "Default": "Warning"
    }
  },
  "Printers": {
    "prn1": { "Uri": "bg.zk.zfp.com://COM1" },
    "prn2": { "Uri": "bg.dt.p.isl.tcp://192.168.1.100:4999"  }
  },
  "AutoDetect": true,
  "Kestrel": {
    "EndPoints": { 
      "Http": {
        "Url": "http://0.0.0.0:8001"
      }
    }
  }
}

Support for non-default operator and operatorPassword

Currently, only the default operator and password are passed to the fiscal printer for each printing job.

This is fine for factory default setup printers. However, the printers might have special setups for operators and passwords.

The solution is to support non-default "operator" and "operatorPassword" in the JSON body for all POST requests. This includes:
/receipt
/reversalreceipt
/deposit
/withdraw
/xreport
/zreport
/datetime

For example:

http://localhost:8001/printers/dt517985/deposit

BODY:

{
    "amount":12.34,
    "operator": "0001",
    "operatorPassword": "1234"
}

If "operator" or "operatorPassword" are not specified, the defaults should be used.

Support /xreport

The fiscal printers support both "xreport" and "zreport". The FP library already supports "zreport". The current task is to make support for "xreport".

(1) Support POST /xreport
(2) Rename "/zeroingreport" to just "/zreport"

Improve the console

Make the following changes to the console window:

(1) Use fixed-width font

(2) The default console window size should be able to show 80x25 characters.

(3) [BUG] The messages are shown on the same line - not CR & LF-ed to new line for each message.

(4) [OPTIONAL] Support setting "Console Verbosity Level" in the tray menu.
Possible levels:

  • Minimal - Only Show Warnings/Errors
  • Normal - Show Normal Messages (DEFAULT)
  • Debug - Maximum Verbosity

The "Normal" level (or whatever it is called) should include "Found 3 printers" and similar messages. The idea is that, by default, we can see the detected/configured printers in the default console.

NOTE: Changing the verbosity level should be saved to the config and applied to the running instance immediately.

Keep the last 9 versions of debug.log

Each starting and stopping of the server creates a debug.log file.

The current task is to keep up to 9 previous versions of debug.log. E.g., keep the debug.log generated by the current and the previous 9 start-stop cycles.

Payments mapping

Payments mapping is hard coded
Current defaults cover only device defaults but companies can change payment name on every payment type. So we need some kind of setup of payments (probably in appsettings.json) for GetPaymentTypeText to avoid resetting of devices.

My suggestion is new optional object in appsettings under printers items
Example:

    "Printers" :  {
      "dt769373" :  {
        "Uri" : "bg.dt.p.isl.com://COM3"
        "PaymentTypes" :  {
          "card" :  "N",
          "cash" : "P",
          "packaging" : "I",
          "check" :  "C"
        }
      },
      "zk125928" :  {
        "Uri" : "bg.zk.zfp.com://COM2",
        "PaymentTypes" : {
          "card" : "7",
          "check" : "3",
          "cash" : "0",
          "packaging" : "4",
          "loyalty" : "2"
        }
      }
    }

Simplify result JSON formats

(1) ResultInfo
Used by:

  • /printers/xxx/reversalreceipt
  • /printers/xxx/deposit
  • /printers/xxx/withdraw
  • /printers/xxx/xreport
  • /printers/xxx/zreport
  • /printers/xxx/datetime

Fields ("ok" SHOULD be the first field):

  • ok: true/false
  • messages: Array Of:
    type: info / warning / error
    code - standard code of the message. null if there is no standard code for the message.
    text

Example:

{
  "ok": "false",
  "messages": [
    { 
      "type": "error",
      "code": "ERR03",
      "text": "The fiscal memory is full."
    },
    ...
  ]
}

(2) PrinterStatusResultInfo: ResultInfo
Used by:

  • /printers/xxx/status
  • /printers/xxx/datetime

Fields:

  • deviceDateTime (contains the word "device" to signify that this is the printer device time and not just the time of the PC, where the lib is running)

Example:

{
  "ok": "true",
  "messages": [
    { 
      "type": "warning",
      "code": "WRN02",
      "text": "Revenue agency reporting temporary problem."
    },
    ...
  ],
  "deviceDateTime": ...
}

(3) PrintReceiptResultInfo: ResultInfo
Used by:

  • /printers/xxx/receipt

Fields:

  • receiptNumber
  • receiptDateTime
  • receiptAmount
  • fiscalMemorySerialNumber

Example ("code" is not specified, because it is null for the included message):

{
  "ok": "true",
  "messages": [
    { 
      "type": "info"
      "text": "Device registers are set."
    },
    ...
  ],
  "receiptNumber": ...,
  "receiptDateTime": ...,
  "receiptAmount": ...,
  "fiscalMemorySerialNumber": ...
}

Server version in the log and console

This will allow better debugging, because we will have a reference to the version of the server that created the debug.log file and console output.

Admin page and /service api

Improving admin page and service api.
Introducing server variables - /service/vars, forcing detection of printers - /service/detect, list of configured printers - /service/printers, configure new printer - /service/printers/configure and deleting/removing printer from configured printers list - /service/printers/delete
From admin page, with link to folder wwwroot/debug, the file debug.log and history of debug.log files - debug.log.[1-9].zip can be downloaded.

Retain COM port open

ErpNet Retains COM port open although there is no printer
After autodection phase ErpNet continue without close serial port that no printer detected.

POS terminals, scales or other hardware on this ports will not to work
If we have POS terminals, scales or other hardware that communicating occasionally they will fail on next try, because port is already opened.

I am not a C# master but suggest fixing in Transport.cs -> ComTransport.cs

        public override void CloseChannel(string address)
        {
            if (openedChannels.TryGetValue(address, out Channel? channel))
            {
                channel.Dispose();
                openedChannels.Remove(address);
            }
        }

and in Provider.cs after drivers iteration try:

                    if (!Found)
                    {
                        transport.CloseChannel(availableAddress.address); 
                    }

That fix is working for me.

Return fiscal memory number on each printing of fiscal receipt

The user information system needs to record the "fiscal memory serial number" (FMSN) for each printing transaction.

Currently, the FMSN can be obtained by a call to GetPrinterInfo. However, we need to have transactional consistency and guarantee the FMSN to which each receipt is printed.

Desired change:
In the dataset, returned by PrintReceipt/PrintReversalReceipt, include the FMSN on which the receipt/reversal was printed.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.