Skip to content

Develop to Main - #358

Closed
Muhayustrid wants to merge 20 commits into
BrainWise-DEV:developfrom
Muhayustrid:develop
Closed

Develop to Main#358
Muhayustrid wants to merge 20 commits into
BrainWise-DEV:developfrom
Muhayustrid:develop

Conversation

@Muhayustrid

Copy link
Copy Markdown

No description provided.

Muhayustrid and others added 20 commits August 31, 2026 22:54
Ports the ownership model from the selling_additional app: a Price Group owns one generated Price List, the unscoped Item Price rows on it, and the POS Profiles matching its outlets. Owner fields are renamed to the custom_pos_next_* namespace since this is a different app.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Both child tables exist only to be referenced by the Price Group parent, so they land together. Outlet carries read-only pos_profile and status columns the controller fills in on save.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
The controller owns one generated Price List (PG-<name>), the unscoped Item Price rows on it, and the POS Profiles matching its outlets. All writes are targeted db.set_value rather than document saves: saving a Price List runs PriceList.on_update, which rewrites every Item Price on the list and can claim the global Selling default. Disabling keeps managed rows for re-enable; deleting restores every owned profile and retains the Price List disabled.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
hooks.py:fixtures exports only Role and Custom DocPerm, so the four owner fields cannot ship as a fixture and are upserted idempotently instead. Validation is left on so CustomField.validate computes idx from insert_after and catches fieldname conflicts. uninstall removes the same four.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
custom/*.json is a review mirror only, never applied. The pos_profile.json entries are additive: the bench exporter drops custom_brands_table because its module is unset, so the two new fields were merged into the committed file by hand instead.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
python -m unittest imports test modules before frappe.init, and bench run-tests dies on ERPNext bootstrap, so neither can run this app's tests. This inits and connects to the site first. sys.path[0] is rewritten to the app root because the nested pos_next/pos_next package would otherwise shadow pos_next.pos_next.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
31 tests ported from selling_additional covering enable/disable, ownership claim and restore, managed vs unmanaged Item Price rows, stock-UOM identity moves, lock ordering, and concurrent claims. They live outside the doctype folder on purpose: inside it frappe derives cls.doctype and generates test records, which imports ERPNext test utils and dies on a DuplicateEntryError for Standard Buying.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
The modified timestamp is bumped because import_file_by_path skips any workspace file whose modified is not newer than the row in the database, which silently drops workspace edits on migrate.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
The sidebar previously existed only as an auto-generated database row from after_app_install, which runs once and never updates. Shipping it as a standard app-level file makes frappe sync it on every migrate.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Replaces the computed quick-amount row with fixed banknote face values (2K/5K/10K/20K/50K/100K) plus a Pas button for the exact remaining, shown only when the selected method is cash and the currency is IDR. Cashiers tender physical notes, so face values match the workflow better than derived round-ups. Non-IDR and non-cash keep the existing quick amounts. Applied to both the desktop and mobile layouts.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Master carries base_price + non-stock parent item; child tables model
mandatory items, choice groups (min_qty..max_qty units across options),
per-option price adjustments, and outlet scoping. Replaces the
pick-count-only promo model from selling_additional so optional mixed
selections (e.g. up to 3 vouchers of any mix) are expressible.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
get_packages serves full definitions for offline caching; quote_package
prices a selection. validate_invoice_packages re-quotes every package on
Sales Invoice validate and recalculates totals, since Frappe runs the
controller's validate before app hooks — otherwise a tampered payload is
repriced but still charged the old grand_total.

Returns are mirrored against the original invoice: package membership is
re-derived through sales_invoice_item because the POS return payload
strips the package fields, so a credit note cannot refund the priced
parent while dropping the components.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Register validate_invoice_packages on Sales Invoice validate and manage
the four pos_package* custom fields on Sales Invoice Item through the
install.py contract (fixtures do not export Custom Field) and
uninstall.py cleanup.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Client-side quote mirrors the Python pricing deterministically and is
authoritative for offline previews; definitions are cached in IndexedDB
via the offline worker so included items, per-option is_stock and UOM
travel offline. Tests lock the mixed-max-3 and per-option-cap rules.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Package items carry a badge in the catalog and open a styled selection
dialog: single-pick groups as toggles, multi-pick groups as steppers
honoring min/max with live running total. Each instance owns its cart
lines via package_instance (never merged with loose items), renders
nested under the priced parent in the cart, and emits the pos_package
fields for server re-quoting. Components use their real Item stock flag;
batch/serial auto-pick at submission.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
feat: POS Package (paket bundling)
…d server quote

In-session POS profile switches kept showing the previous outlet's
packages (global hasFetched), and a server rejection (wrong outlet,
expired, edited definition) fell back to a locally-valid quote — which
the invoice later refuses at sync. The store is now keyed by profile
and surfaces the rejection as an error the dialog can show.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Forward-port from 9212350; resolved 3 conflicts by keeping both sides:
- pos_next/_pn_run_tests.py: SITES_PATH env + sys.path/bench-root fixes
- pos_next/install.py: pos_package + Price Group custom-field syncs
- pos_next/uninstall.py: both cleanup lists
@Muhayustrid Muhayustrid closed this Sep 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant