Stand alone POS in React Native

Pouch is server side too but yes, I agree, SQLite is much more close to current MariaDB schema. Not sure about synchronization simplicity because there are still two different engines with no included sync and conflict management between them (but there may be open source libraries to help here). Will be interested to see how you will deal with that (and how have done Frappé team with current offline POS). Good luck !

1 Like

Keep in mind that for the POS there is no much of two way synchronizations. you are basically caching many tables that are not changing at the POS app like item_data, price_list_data, pricing_rules, serial_no_data, item_groups…etc as they will just be used for validating the business logic
when the POS is online you are just going to push back api calles to create sales invoices, added new customers in the system
and here is the local storage caching in the current implementation
https://github.com/frappe/erpnext/blob/8919669ac2c1e2c67df29ffc5c919ab7732ffd55/erpnext/accounts/page/pos/pos.js#L319

1 Like

There are so many new frameworks, platforms and stacks today it makes my head spin. :confounded:
I didn’t know that React Native was heading towards supporting desktops.
I agree that compiling to native should produce faster, smaller apps. (Not sure about more secure, but I guess the run time is another attack vector?).
The ideal platform for most POS deployments is a touch screen device so iOS and Android are a perfect fit. Although I do see a lot of shops using touch enabled windows devices for POS though.
An electron OSX desktop app starts at about 50MB just for the runtime. After that it s pretty efficient though. As for speed electron has improved a lot over the year. Atom editor is a good example.
DB sync and conflict resolution is a major. For a lot of retail situations the only conflicts I can think of are the number of items still in stock? There is a popular POS cloud app called vend. It might be worth signing up for 30 day trail and see what DB sync method they use?

  • yup because now people are ditching hybrid frameworks that relies on web views to more native experience, the main frameworks that competing in this area now are react-native which is perfect for web apps already built on react, nativescript more general, Weex for web apps built on Vue.js, XAMARIN for shared C# codebase

  • It is more secure since the device admin is able to prevent the end users from uninstalling the apps, the SQLite in the app can be encrypted, the app can be prevented from installing on rooted devices

  • I’m not a big fan of electron at all. I seriously think it is just like flash for desktops and soon will it will die as flash did. Anyway, my priority here is for mobile since basically tablets are what we use.

  • Vend uses local storage on the browser just like Erpnext does, but not sure about the app I will search it

You may add Kivy to the list, Python touch friendly framework which can run on desktops and mobile devices. About Electron / Flash comparison, not sure about that. Electron is mostly packaged Chrome browser alongside NodeJS, not a specific runtime with its own stack.

Maybe he refers to the fact that electron doesn’t support mobile devices?

@ganas Agree with all your points.
Touch centric iOS & Android devices with silo separated apps lend themselves perfectly to the POS Task. Bar code scanners,Receipt printers, CC Debit card machines and Cash drawers are all supported in iOS.
It looks like Vend have put a lot of effort into their iOS app. I guess this is why. haven’t used it btw.
I like the idea of a “seperate” cash register app because:
A Cashier user account would still be created by office admin in ERPNext.
Each POS Cash Register would allow a cashier to sign in (so erpnext can track their sales etc). But as the cash register only exposes cash register related data like Price, Available stock and stock location this would limit exposure to larger scope ERPNext data. I suggest two new User types. Cashier and Cashier Floor Manager. Cashier can only sell. Cashier Floor Manager can also delete sale.
I would consider local DB encryption and SSL encryption to be minimum requirements.

I am really loving the direction of this conversation guys.

This is music to my ears

@Yakulu I know electron inner working and just packing Node with Chromium Engine. what I meant by comparing it to flash is that its structure is not sustainable for the future. Yes it is hybrid platform that provide fast entry to desktop market but soon it will be taken over by native cross platform framework. For example, look at Slack desktop app in its memory foot print and extensive use of resources and CPU given the countless times that Slack tried to solve some of these problems Here is there latest attempt Reducing Slack’s memory footprint. Thats why now Slack are transitioning their web client to React Rebuilding Slack’s Emoji Picker in React and after they are done that for their web app, I’m sure you will see them jumping the ship from Electron to React native.

Thats why to be honest I was surprised when I heard Frappe team introducing Erpnext Desktop based on electron. Those resources should have been toward migrating from the dying JQuery to prepare Erpnext for the future. but maybe the frappe team has different point of view

Interesting.
I still like the idea of a seperate “plug in” POS App that interfaces with the more complex Frappe/ERPNext. Moving the entire Frappe/ERPNext to React Native would be too much of a headache I would have thought. Once the Frappe POS module is completed than maintaining two seperate source codes should be not much of an issue as the API shouldn’t change too much. Possibly?

@System19 oh yeah I didn’t mention any changes on Erpnext core. The App is separate and is only utilizing the RESTful API which I hope won’t change much. We are pass this point, and I will be using NativeScript as framework.
Now I’m focusing on the best structure to enable continues sync like should use SQLite or more advance and efficient sync with Couchbase but more complex.

Thats why I like getting inputs in this topic so we can collectively decide the best approach before moving forward.

+1 NativeScript…POS needs to be able to talk with supporting devices like customer monitor screen, EDC devices etc…I think native apps has advantages here

Yes I agree that launching a full browser, probably the heavier in the market (Chrome) for a single app can be heavy. That said, it may be more understandable for ERP (Frappé Desktop) than for discussion app. Proposing alternative implementation with no Python will already be a huge task. That’s why I understand they choose Electron here.

ERP own framework has to be tied to back-end to be efficient. For example Odoo also has its own JS Web framework based on jQuery and elements from BackboneJS. Using something like React for Frappé JS is debatable (and would be a huge rework for all apps + porting or wrapping many existing jQuery widgets). And, as you know, in frontend programming, each year you got a new winner (Backbone then Angular then React then Vue.JS…). Not really stable ATM.

For the topic subject, I also support the idea of local encrypted database. In some countries, POS need to be certified or attested and you engage your responsibility, as a service provider if customer can easily cheat tax authorities with their POS application…

1 Like

@ganas please keep us posted with progress or questions as am interested.
Vend does really well in covering most bases and has been very successful in NZ and Aus. If you get stuck with work flow or UI then take a look at Vend.

@Yakulu

Regarding electron making more sense when running large apps like ERPNext.

Agreed.

in frontend programming, each year you got a new winner

Sadly Agreed

In some countries, POS need to be certified or attested

Agreed

@netchampfaris in pos.py I see the two api get_pos_data() which returns the whole date for a pos profile, and make_invoice which adds the created customers, invoices, and send emails in the queue.

my question is shouldn’t also be a third api ( e.g get_pos_updated_data() ) that acts as get_pos_data() but it takes a timestamp and returns any data updated after this timestamp? so instead of syncing the whole data at each time the app starts, I can utilize this API to sync only the difference (also its applicable to the offline web pos). For this it is not hard i can use the fields creation and modified in each table to compare the timestamp with
However, the challenge here is how to make this API also return indexes of items, customers …etc deleted at the backend

Just thoughts:
Agreed. Limiting app sql & frappe/erpnext traffic should be the main focus. Do the apps really need up to the minute stock inventory? If not great, Run a 30 min / hourly / lunchtime cron job that downloads all the stock/services/numbers onto POS app and index that into sqlite. Keep us posted.

Hi @revant_one, sorry to tag u but I have few questions, right now I’m utilizing the username and password and using cookies to access APIs; however, my questions as follows:

  • List item Is there a white listed API that returns a list of available social logins?
  • how can I get a token from a social login given the fact that I don’t have access to the client secret or control over the redirect URL. something is not clear for me here.

for Some reason the gif gets cut (maybe its long) anyway check the link
https://streamable.com/s/soysy/ubnt

@rohit_w is it possible to let erpnext.accounts.doctype.sales_invoice.pos.get_pos_data method accept optional timestamp and only return updated records after the time stamp. It is troublesome to re-sync the whole data again and again especially when the data is huge.

For others who are interested, I’m hard at work on the app and hope will give alpha demo in few weeks.

1 Like

Yes this can be possible, using modified date you can get the updated records.

@rohit_w I’m trying really hard to stick to the core API not revert to creating my APIs in custom app; however, I find things in the API that are counter intuitive and don’t understand (maybe you can help understand the reason you guys choose this design decision). For example, the get_pos_data api return de-structured customer data, address, and contacts each in its own object, why not return data structured for each customer as it was beatifly retrieved from the database already structured. e.g. return each customer object with its informations are contained within as

 { "customer_name" : "John Smith",
    "customer_pos_id": "1469029434776",
    "customer_group": "All Customer Groups",
    "territory": "Canada",
    "customer name": "John Smith",
    "address": [
        {
            "address_line1": "1 King St N",
            "city: "Toronto",
            "fax: "19056775654",
            "address_line2: "",
            "name: "John Smith home",
            "email_id: "JohnSmith@gmail",
            "pincode: "L6T 7X2",
            "phone: "2897765453",
            "state: "Ontario",
        }
    ],
    "contact": {
        "email_id": "John@gmail.com",
        "phone": "2893356787",
        "mobile_no": "9056678786"
    }
}

and the same applies for many other objects in doc.

For my work now, I’m using Couchbase Lite as my document store database, when I receive the data I have to do lots of dirty work to link related objects before I add them as one document and in that document I add private property e.g. “_type”:“customer” or “_type”:“customer” and then based on those types I setup views that create persistent indexes which later I use for Map/reduce queries …etc.

The other thing is customer_pos_id is not fully utilized where it can makes life much easier. Why not make it mandatory and populate it on customer creation outside the pos.

I’ve been following your PRs and I know you are hard at work refactoring online pos, so is there plans to change the apis for the offline pos.

Yes soon we’re going to start work on offline pos refactor, in which we’ll modify the api data and mechanism to store offline data.