frappe / books

Free Accounting Software
https://frappe.io/books
GNU Affero General Public License v3.0
2.86k stars 660 forks source link

feat: point of sale #709

Closed akshayitzme closed 10 months ago

akshayitzme commented 1 year ago

This PR brings the Point of Sale feature to Frappe Books!

Items Table (table below the Item Search)

Effects on Accounts (feel free to evaluate)
**When POS Shift is Opened** - Users can mention the Opening Amounts of Cash and Transfer payment methods when creating a POS Shift. - If an Opening Cash Amount is set, a Journal Entry will be created to transfer the Opening Cash Amount from **Cash** account to **Counter Cash** account (_Counter Cash Account must be set beforehand in the POS Settings_). **Opening Amounts** | Payment Method | Amount | |----------------|--------| | Cash | 100 | **Journal Entry** | Account | Dr | Cr | |--------------|-----|-----| | Counter Cash | 100 | 0 | | Cash | 0 | 100 | **SINV Payments** - SINV Payments are made to **Counter Cash** Account. **When POS Shift is Closed** - When the POS Shift Closes the total transacted cash amount is transferred from **Counter Cash** Account to **Cash** Account. also creates write-off entries if any mismatch occurs between the total transacted Cash Amount and Closing Cash Amount (_cash in the counter_) 1. Expected and Closing Amounts are equal | Payment Method | Closing Amount | Expected Amount | Difference | |----------------|----------------|-----------------|------------| | Cash | 100 | 100 | 0 | **Journal Entry** | Account | Dr | Cr | |--------------|-----|-----| | Cash | 100 | 0 | | Counter Cash | 0 | 100 | 2. Closing Amount < Expected Amount (_shortage of Cash_) | Payment Method | Closing Amount | Expected Amount | Difference | |----------------|----------------|-----------------|------------| | Cash | 50 | 100 | -50 | **Journal Entry** | Account | Dr | Cr | |--------------|----|----| | Cash | 50 | 0 | | Counter Cash | 0 | 50 | | Cash | 50 | 0 | | Write Off | 0 | 50 | 3. Closing Amount > Expected Amount (_excess of Cash_) | Payment Method | Closing Amount | Expected Amount | Difference | |----------------|----------------|-----------------|------------| | Cash | 150 | 100 | 50 | **Journal Entry** | Account | Dr | Cr | |--------------|-----|-----| | Cash | 150 | 0 | | Counter Cash | 0 | 150 | | Write Off | 50 | 0 | | Cash | 0 | 50 |

References

POS Icon Source: store-3-fill - RemixIcon

18alantom commented 1 year ago

@akshayitzme regarding the 3 failing tests cases. I'd suggest debugging the DB state using the CI env.

A thing to check is, have prior async statements been awaited. I think this might be the cause. I've faced similar issues before where this was the root cause.

Reasoning:

CI takes 1m 15.4s to execute the test, local (mine) takes 15.2s.

This could mean that on the faster computer, a non-awaited statement has a higher chance of executing completely before getPOSTransactionAmount has been called, which means that when it executes the DB is in the expected state.

Where as on the slower computer (∵ of slower IOPS), the non-awaited statement hasn't completed its execution when getPOSTransactionAmount is called.

Debugging:

Start with the test file (testPointOfSale.spec.ts). I think non awaited statements should've been caught by the linter. If the test file doesn't have it, then check the code that's being run while running the test.

One way to substantiate this hypothesis is to place a sufficiently long sleep statement before getPOSTransactionAmount is called, this should cause the failing test to pass as the non awaited statement would've executed completely.

akshayitzme commented 1 year ago

@akshayitzme regarding the 3 failing tests cases. I'd suggest debugging the DB state using the CI env.

A thing to check is, have prior async statements been awaited. I think this might be the cause. I've faced similar issues before where this was the root cause.

Reasoning:

CI takes 1m 15.4s to execute the test, local (mine) takes 15.2s.

This could mean that on the faster computer, a non-awaited statement has a higher chance of executing completely before getPOSTransactionAmount has been called, which means that when it executes the DB is in the expected state.

Where as on the slower computer (∵ of slower IOPS), the non-awaited statement hasn't completed its execution when getPOSTransactionAmount is called.

Debugging:

Start with the test file (testPointOfSale.spec.ts). I think non awaited statements should've been caught by the linter. If the test file doesn't have it, then check the code that's being run while running the test.

One way to substantiate this hypothesis is to place a sufficiently long sleep statement before getPOSTransactionAmount is called, this should cause the failing test to pass as the non awaited statement would've executed completely.

Thanks! .. I'll check

akshayitzme commented 1 year ago

@18alantom, regarding the previously failed unit tests,

I crafted a Linux VM with 1024 MB RAM and one processor core. adjusted the Processor Execution Cap accordingly to emulate a slower IOPS machine. a dry run of the unit test took 2m 11s to complete ( :100: perfect !).

I ran the tests against this branch. Yep, got em.

I checked for any missing async/await. Couldn't find any. After some debugging, found that the issue was triggering on the fromDate and toDate in the getPOSTransactionAmount function.

Solution: I refactored the code to find Sales Invoices created from POS between the given dates. used luxon to get the date in ISO Date format (yyyy-mm-dd).

that fixed the failing tests.

@18alantom, Could you review this PR when you get time ?