erpnet / erpnet.fp Goto Github PK
View Code? Open in Web Editor NEWErpNet.FP is a light-weight cross-platform Http server facilitating printing to fiscal printers through simple JSON Api.
License: BSD Zero Clause License
ErpNet.FP is a light-weight cross-platform Http server facilitating printing to fiscal printers through simple JSON Api.
License: BSD Zero Clause License
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.
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.
What is incorrect in this request?
Thanks in advance for any help.
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
Expected behavior
In step 2. task should return state finished with error E404.
Screenshots
debug.log.1.zip
Additional context
The menu options are:
Notifications for:
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.
TaxGroup will be from 1 to 8
PaymentType will be one of:
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"
}
}
}
Adding TaxNumber - Fiscal Subject Identification Number, in Device Info.
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"
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 :(
Describe the bug
Reversal reason "operator-error" prints RETURN on paper.
A "refund" reason prints OPERATOR ERROR
Describe the device(s) you are using
Datecs DP-150 in non-fiscal mode
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.
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.
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
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:
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.
{
"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"
}
}
}
}
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:
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.
(1) ResultInfo
Used by:
Fields ("ok" SHOULD be the first field):
Example:
{
"ok": "false",
"messages": [
{
"type": "error",
"code": "ERR03",
"text": "The fiscal memory is full."
},
...
]
}
(2) PrinterStatusResultInfo: ResultInfo
Used by:
Fields:
Example:
{
"ok": "true",
"messages": [
{
"type": "warning",
"code": "WRN02",
"text": "Revenue agency reporting temporary problem."
},
...
],
"deviceDateTime": ...
}
(3) PrintReceiptResultInfo: ResultInfo
Used by:
Fields:
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": ...
}
{
"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"
}
}
}
}
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"
}
]
}
}}
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.
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.
The idea is that each printing request will be enqueued in a queue.
(1) /printreceipt
will:
(2) /printreceipt?asynctimeout=15000
will:
(3) /printreceipt?asynctimeout=0
will:
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"
}
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
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"
}
]
}
The idea is to have a virtual printer, which can be used for debugging purposes. It will just output the input text to the console.
It would be nice, if it returns results in the same format as the "official" printers. Of course, the results would be dummy.
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.
Optional timeout parameter in milliseconds, implemented for slow controller methods i.e. ?timeout=2000.
See Issue #13
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).
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.
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.
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.
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.
Versions for Linux, Mac OS X, Raspbian
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.
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.
It will have tray icon with menu, and will show tooltips for statuses.
The menu options are:
Notifications for:
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.
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.
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.
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
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.