From 66282c21ac0ddbe276dccb7fb35b9dc84dda4542 Mon Sep 17 00:00:00 2001 From: Tyler Matteson Date: Fri, 26 Jul 2024 11:51:02 -0400 Subject: [PATCH] chore: refactor to version-15 --- .pre-commit-config.yaml | 10 +- CHANGELOG.md | 1421 +++++------ inventory_tools/docs/faceted_search.md | 3 + inventory_tools/docs/index.md | 3 + inventory_tools/hooks.py | 2 +- inventory_tools/inventory_tools/boot.py | 19 +- .../inventory_tools/custom/color.json | 125 +- .../inventory_tools/custom/operation.json | 72 - .../doctype/specification/__init__.py | 2 + .../doctype/specification/specification.json | 256 +- .../specification_attribute/__init__.py | 2 + .../specification_attribute.json | 186 +- .../doctype/specification_value/__init__.py | 2 + .../specification_value.json | 183 +- .../specification_value_list.js | 3 + .../inventory_tools/faceted_search.py | 9 +- .../inventory_tools/overrides/stock_entry.py | 46 +- .../report/specification/__init__.py | 2 + .../report/specification/specification.json | 56 +- .../patches/rename_alternative_workstation.py | 25 +- .../js/faceted_search/AttributeFilter.vue | 4 +- .../js/faceted_search/FacetedSearch.vue | 81 +- .../FacetedSearchColorPicker.vue | 223 +- .../faceted_search/FacetedSearchDateRange.vue | 135 +- .../FacetedSearchNumericRange.vue | 137 +- .../public/js/faceted_search/api.js | 3 + .../js/faceted_search/faceted_search.js | 3 + .../js/faceted_search/specification_dialog.js | 3 + inventory_tools/public/js/vite.config.js | 11 +- inventory_tools/tests/fixtures.py | 2192 +++++++++-------- inventory_tools/tests/setup.py | 880 +------ .../tests/test_alternative_workstation.py | 77 +- inventory_tools/tests/test_faceted_search.py | 219 +- package.json | 50 +- 34 files changed, 2898 insertions(+), 3547 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 6250678..ad32f63 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -36,17 +36,11 @@ repos: - id: flake8 additional_dependencies: ['flake8-bugbear'] - - repo: https://github.com/pre-commit/mirrors-mypy - rev: v1.5.1 - hooks: - - id: mypy - exclude: ^tests/ - args: [--ignore-missing-imports] - - repo: https://github.com/agritheory/test_utils - rev: v0.14.0 + rev: v0.14.1 hooks: - id: update_pre_commit_config + - id: mypy - id: validate_copyright files: '\.(js|ts|py|md)$' args: ['--app', 'inventory_tools'] diff --git a/CHANGELOG.md b/CHANGELOG.md index 26e0dc7..ae01dd1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,6 @@ + + <<<<<<< HEAD # CHANGELOG @@ -21,713 +24,713 @@ * feat: allow user to bulk upload items with quantity to shopping cart (#70) ======= -# CHANGELOG - - -## v14.6.0 (2024-05-13) - -### Chore - -* chore: update quotation demand docs (#77) ([`f168079`](https://github.com/agritheory/inventory_tools/commit/f168079e29d99056d4c5eb2321d84957cff84f3b)) - -### Feature - -* feat: add inventory tools settings to boot (#81) ([`7ac2e15`](https://github.com/agritheory/inventory_tools/commit/7ac2e15aa74676ba5741887231814cdf9e675755)) - - -## v14.5.0 (2024-04-29) - -### Feature - -* feat: allow user to bulk upload items with quantity to shopping cart (#70) - +# CHANGELOG + + +## v14.6.0 (2024-05-13) + +### Chore + +* chore: update quotation demand docs (#77) ([`f168079`](https://github.com/agritheory/inventory_tools/commit/f168079e29d99056d4c5eb2321d84957cff84f3b)) + +### Feature + +* feat: add inventory tools settings to boot (#81) ([`7ac2e15`](https://github.com/agritheory/inventory_tools/commit/7ac2e15aa74676ba5741887231814cdf9e675755)) + + +## v14.5.0 (2024-04-29) + +### Feature + +* feat: allow user to bulk upload items with quantity to shopping cart (#70) + >>>>>>> 12d5afa2ce39627719b130a5ed0e5ce879c818f6 -* feat: allow user to bulk upload items with quantity to shoping cart - -* nit: variable and syntactical changes - -* fix: removed line by line order placing, optimised code, added enqueue - -* fix: minor cleanup - ---------- - -Co-authored-by: Rohan Bansal <rohan@agritheory.dev> ([`748a9bc`](https://github.com/agritheory/inventory_tools/commit/748a9bc85034094dcd60544fe2b822b67322fb44)) - -### Unknown - -* Aggregate and/or Split Quotations into multiple Sales Orders (#65) - -* feat: Quotation Demand - -* feat: hook - -* feat: settings for quotation demand - -* feat: fixes, SO validate_warehouse - -* feat: quotation demand tests - -* feat: documentation - -* feat: improvements - -* feat: improve tests - -* feat: total selected, price, draft so - -* feat: tests ([`6eceeb5`](https://github.com/agritheory/inventory_tools/commit/6eceeb5623856d659db1ffc3dd7a3ce352cd8000)) - - -## v14.4.0 (2024-04-25) - -### Ci - -* ci: add black to ci (#61) - -* ci: add black to ci - -* chore: black ([`db5a742`](https://github.com/agritheory/inventory_tools/commit/db5a7427f068d7005f8f07125d81f1430c49eb9b)) - -### Feature - -* feat: aggregate POs (#71) ([`5ff8fee`](https://github.com/agritheory/inventory_tools/commit/5ff8fee2ef356990e2dcda0d2db76d1b856a0685)) - -### Unknown - -* Material Demand Test (#64) - -* wip: material demand tests - -* test: material demand aggregation tests and fixes with and without warehouse - -* test: material demand tests and bug fixes - -* chore: add mypy types isntall - -* fix: remove duplicate function - -* tests: add pytest runner file - -* tests: add helper files - -* tests: correct app name - -* ci: fix site_config - -* ci: update action version to use node 20 - -* ci: hrms get-app - -* ci: add base branch sensitvie get-app - -* ci: add hrms to install - -* ci: add node 20 versions - -* ci: remove hrms from install-apps - -* ci: get-app for hrms - -* ci: update prettier and changed-files actions - -* ci: ad dhrms to apps.txt - -* ci: get-app for hrms again - -* ci: get-app for hrms only - -* ci: overrite erpnext install (hrms is tryign to install develop branch) - -* ci: add app name - -* ci: add repo to required apps - -* ci: try install hrms first with overwrite - -* ci: remove "install_apps" key from site_config - -* ci: remove required apps - -* feat: use query builder - -* ci: remove resolve deps - -* ci: fix install apps - -* test: fix manufacturing capacity test and report - -* test: cleanup uom test - -* test: fix error message assert - -* test: add ordering - -* fix: test - -* fix: use frappe function - -* fix: use frappe function - ---------- - -Co-authored-by: fproldan <franciscoproldan@gmail.com> ([`6f4f63f`](https://github.com/agritheory/inventory_tools/commit/6f4f63f22f3f7278e20c6aba9e5ef6a021ae03b2)) - -* Manufacturing capacity report (#57) - -* ci: update app in str(file path) code to more exact matching - -* chore: remove unused code - -* feat: add manufacturing capacity report - -* tests: start manufacturing capacity report tests - -* chore: uncomment formatting code - -* docs: add manufacturing capacity report documentation - -* fix: div by zero in parts can build calc - -* docs: update for calculation differences - -* fix: in stock qty to zero if none from query ([`2936cde`](https://github.com/agritheory/inventory_tools/commit/2936cde9aac6583edeb383d94d74142461cf243a)) - - -## v14.3.0 (2024-03-01) - -### Feature - -* feat: Alternative workstation in job card and operation (#56) - -* feat: New field and link filters to select alternative workstation - -* fix: add alternativ workstation in fixture - -* fix:change alternative workstation in fixture - -* change to error key function - -* fix: set validation on workstation if not operation - -* changes field name in testcase - -* fix: change a class base function to saperate function - -* added a searchfield in query - -* added a searchfield in query - -* added a searchfield in query - -* added a searchfield in query - -* added a searchfield in query - -* feat: validation to not allow default workstation in alternative - -* added comment on function ([`0788d3c`](https://github.com/agritheory/inventory_tools/commit/0788d3caa67ad7820a5a3cdfdc950c85bd6f0cd7)) - -### Unknown - -* Prompt Material Transfer upon Completion of Manufacturing Stock Entry (#51) - -* feat: wip stock entry next action - -* feat: improve message - -* fix: on_submit hook - -* fix: parameter hardcoded - -* feat: change wording ([`d1e126b`](https://github.com/agritheory/inventory_tools/commit/d1e126b8dbaf09370f6d4c173e24af33ac994bd7)) - - -## v14.2.0 (2024-02-01) - -### Feature - -* feat: manufacturing over/under production - -* feat: WIP Manufacturing Over/Under Production - -* feat: WIP Manufacturing Over/Under Production - -* feat: WIP Manufacturing Over/Under Production - -* fix: unused import - -* feat: override onload for work order - -* feat: oveeride get_pending_raw_materials - -* fix: allowed_qty in job card - -* fix: indentation - -* fix: import - -* fixes - -* wip: tests - -* feat: test_get_allowance_percentage - -* feat: test test_validate_finished_goods - -* fix: validate_job_card and test - -* fix: test ([`baeb469`](https://github.com/agritheory/inventory_tools/commit/baeb4690d42429a062595eb9058ddd2770b190c9)) - -### Unknown - -* Make Creation of Job Card(s) on Submit of Work Order configurable (#49) - -* feat: configurable creation of job card - -* feat: configurable creation of job card ([`5bf9486`](https://github.com/agritheory/inventory_tools/commit/5bf94860c58d81faccb1106828f16121c081871a)) - - -## v14.1.3 (2024-01-04) - -### Fix - -* fix: validate customizations (#35) - -* fix: validate customizations - -* fix: only install inventory tools customizations ([`e1d86a0`](https://github.com/agritheory/inventory_tools/commit/e1d86a0739e56f3b987b599c275644ee5c29fc0a)) - - -## v14.1.2 (2023-09-12) - -### Chore - -* chore: remove console.log ([`f82b590`](https://github.com/agritheory/inventory_tools/commit/f82b590d061608818170092f07e3da8d9153b756)) - -### Ci - -* ci: update release action user and email (#32) ([`4264bdd`](https://github.com/agritheory/inventory_tools/commit/4264bdde25c0bff1390923e7f18fce7c353844db)) - -### Fix - -* fix: make uom enforcement respond better to toggle on/off ([`3734cb4`](https://github.com/agritheory/inventory_tools/commit/3734cb42e880168bb4c4a71c67820da63857e0bf)) - -### Unknown - -* Merge pull request #33 from agritheory/uom_enforcement_fix - -fix: make uom enforcement respond better to toggle on/off ([`13ad883`](https://github.com/agritheory/inventory_tools/commit/13ad8832a346799563e0f7ae2f1b20c457d10d5c)) - - -## v14.1.1 (2023-08-30) - -### Fix - -* fix: add is_subcontracted check for additional validation/submit/cancel code ([`8182dac`](https://github.com/agritheory/inventory_tools/commit/8182dacfd35d2a2ee4c5ee94211cbfc7ac00abfd)) - -### Unknown - -* Merge pull request #30 from agritheory/fix_subc_validation - -fix: add is_subcontracted check for additional validation/submit/cancel code ([`c4e7b83`](https://github.com/agritheory/inventory_tools/commit/c4e7b83fd1700d08e8f711e10f1a77c81da0de32)) - - -## v14.1.0 (2023-08-24) - -### Chore - -* chore: update test data for erpnext codebase changes (#24) ([`b7dfc02`](https://github.com/agritheory/inventory_tools/commit/b7dfc02e228c4ebdca86000dac65d1a903640b15)) - -### Ci - -* ci: update remote name ([`021b8a4`](https://github.com/agritheory/inventory_tools/commit/021b8a47355cb9028bac7ac8e60d224247d5b0e8)) - -* ci: update version number ([`9d82150`](https://github.com/agritheory/inventory_tools/commit/9d821506af9d6eb72e3bfb1345ac652aa86896dc)) - -* ci: add python semantic release ([`703803d`](https://github.com/agritheory/inventory_tools/commit/703803df7949fb0cb43699482425ec31595dd1b9)) - -### Documentation - -* docs: update material demand section for expanded functionality ([`1af88f6`](https://github.com/agritheory/inventory_tools/commit/1af88f6d06fdc8e6908381f9dd9011fe470dd9d7)) - -### Feature - -* feat: select email template ([`02196e3`](https://github.com/agritheory/inventory_tools/commit/02196e37c7234982c5dafda9e814117d374565a9)) - -### Fix - -* fix: blank email template for PO; skip supplier-only rows for RFQ ([`2a0e8cd`](https://github.com/agritheory/inventory_tools/commit/2a0e8cd6c6aefdd1a0d7b978652f97ddc755523f)) - -* fix: fix JS after adding draft PO column (#26) ([`e0d3229`](https://github.com/agritheory/inventory_tools/commit/e0d322950e87dcf09f13441859e273a0e44a1192)) - -### Unknown - -* Merge pull request #23 from agritheory/issue_19 - -Allow Creation of RFQ from Material Demand report ([`8a0e350`](https://github.com/agritheory/inventory_tools/commit/8a0e35024968ce5a0f6da05e71f62c091bf2b38f)) - -* Work Order Subcontracting (#13) - -* tests: update test data for additional manufacturing workflow - -* feat: work order subcontracting validations - -* tests: add valuation rate for subcontracted item - -* feat: start wo subcontracting feat - -* feat: make subcontracting section visible by check and settings - -* feat: add ste detail paid field and new pi cols - -* feat: setup hooks and custom po - -* tests: update data for default supplier and price lists - -* feat: include doctype js - -* feat: add work order customizations - -* feat: add purchase order customizations - -* feat: update purchase invoice customizations - -* feat: remove unused code blocks - -* fix: add module to json - -* fix: update custom doc path - -* feat: consolidate custom PI code and modularize class functions - -* feat: combine and refactor PO code - -* feat: update server function paths - -* feat: add BOM field default - -* feat: update to use BOM field vs Item for is_subcontracted - -* feat: code cleanup and refactoring for BOM field - -* feat: update for uom conversion and new svc item - -* fix: move UOM conversions to item - -* add todos in JS - -* feat: rewire item adjustments for conversion factor - -* wip: integrate with production plan - -* feat: add supplier field in WO, allow selection of supplier in dialog - -* chore: add comment explaining precision code - -* wip: subcontractor workflow - -* feat: subcontracting workflow with correct warehouses - -* feat: show/hide subcontracting columns - -* feat: colorize fetach stock entries button - -* fix: text artifacts, new PO errors - -* feat: fetch supplier warehouse, added connectiosn to PI and PO from WO - -* feat: add filters and looks to both PI and PO - -* fix: monkey patch validate_item_details - -* feat: remove buttons and update stockfield in WO subc workflow - -* Enforce UOMs to those that exist in the Item's conversion detail (#27) - -* wip: uom restricted query - -* feat: refactor UOM enforcement validation to be hookable - -* docs: add docs for UOM enforcement - -* tests: fix test logger problem, add xfail uom test - -* Warehouse path (#25) - -* wip: warehouse path - -* wip: warehouse path - -* wip: warehouse path feature - -* feat: warehouse path builder - -* feat: undo query when not configured; setup tweaks - -* chore: update test data for erpnext codebase changes (#24) - -* wip: warehouse path feature - -* wip: test setup - -* chore: update yarn - -* tests: trying to defaeat logger problem - -* test: fix conftest logger issue - -* docs: add docs for warehouse path - -* chore: union types for whitelisted function - ---------- - -Co-authored-by: Heather Kusmierz <heather.kusmierz@gmail.com> - -* tests: test cadence (#28) - -* fix: no cancelled PO in se query, code clean up - -* chore: add comment to explain monkey patch rationale - ---------- - -Co-authored-by: Tyler Matteson <tyler@agritheory.com> ([`ac11c1d`](https://github.com/agritheory/inventory_tools/commit/ac11c1df4daad2189916ca9841480aa1796e42e3)) - -* Merge branch 'version-14' into issue_19 ([`ee0a27f`](https://github.com/agritheory/inventory_tools/commit/ee0a27f0f03a8e3c9e9fa54011d02e44554b8bbb)) - -* Documentation (#29) - -* docs: add index page - -* docs: add screen shots and workflow - -* docs: add screen shots, text edits - -* docs: add example data page - -* docs: add placeholder pages - -* docs: add subcontracting via WO section - -* docs: edits, conform text conventions ([`2fc980d`](https://github.com/agritheory/inventory_tools/commit/2fc980d41105759cffa33e610b779b6d464cf24c)) - -* tests: test cadence (#28) ([`6b5bd47`](https://github.com/agritheory/inventory_tools/commit/6b5bd47089fb2f8a09159635e618425743cc9dff)) - -* Warehouse path (#25) - -* wip: warehouse path - -* wip: warehouse path - -* wip: warehouse path feature - -* feat: warehouse path builder - -* feat: undo query when not configured; setup tweaks - -* chore: update test data for erpnext codebase changes (#24) - -* wip: warehouse path feature - -* wip: test setup - -* chore: update yarn - -* tests: trying to defaeat logger problem - -* test: fix conftest logger issue - -* docs: add docs for warehouse path - -* chore: union types for whitelisted function - ---------- - -Co-authored-by: Heather Kusmierz <heather.kusmierz@gmail.com> ([`370dd6f`](https://github.com/agritheory/inventory_tools/commit/370dd6f9789156ebcbbe7b111d891a74731a477b)) - -* Enforce UOMs to those that exist in the Item's conversion detail (#27) - -* wip: uom restricted query - -* feat: refactor UOM enforcement validation to be hookable - -* docs: add docs for UOM enforcement - -* tests: fix test logger problem, add xfail uom test ([`d4c145a`](https://github.com/agritheory/inventory_tools/commit/d4c145a94d8402fa441619289b4cc6438b7d5c45)) - -* Documentation (#29) - -* docs: add index page - -* docs: add screen shots and workflow - -* docs: add screen shots, text edits - -* docs: add example data page - -* docs: add placeholder pages - -* docs: add subcontracting via WO section - -* docs: edits, conform text conventions ([`198e110`](https://github.com/agritheory/inventory_tools/commit/198e110ab0c5461b9c46925fc05af351151abd38)) - -* tests: test cadence (#28) ([`b91e024`](https://github.com/agritheory/inventory_tools/commit/b91e0246f6e384f40685af40d3a249daa9d03a8c)) - -* Warehouse path (#25) - -* wip: warehouse path - -* wip: warehouse path - -* wip: warehouse path feature - -* feat: warehouse path builder - -* feat: undo query when not configured; setup tweaks - -* chore: update test data for erpnext codebase changes (#24) - -* wip: warehouse path feature - -* wip: test setup - -* chore: update yarn - -* tests: trying to defaeat logger problem - -* test: fix conftest logger issue - -* docs: add docs for warehouse path - -* chore: union types for whitelisted function - ---------- - -Co-authored-by: Heather Kusmierz <heather.kusmierz@gmail.com> ([`e3fb9c7`](https://github.com/agritheory/inventory_tools/commit/e3fb9c7f2a8ed3c42f4cb47078086bcdd60f91c7)) - -* Enforce UOMs to those that exist in the Item's conversion detail (#27) - -* wip: uom restricted query - -* feat: refactor UOM enforcement validation to be hookable - -* docs: add docs for UOM enforcement - -* tests: fix test logger problem, add xfail uom test ([`65d42e1`](https://github.com/agritheory/inventory_tools/commit/65d42e126d81f3ed1b98178f7b6c68c6a070986e)) - - -## v14.0.1 (2023-08-10) - -### Chore - -* chore: update test data for erpnext codebase changes (#24) ([`48160aa`](https://github.com/agritheory/inventory_tools/commit/48160aa27f5d0deb3be5e6e55f16d35fd92ae086)) - -### Ci - -* ci: update remote name ([`218eb06`](https://github.com/agritheory/inventory_tools/commit/218eb06a6a4a2ac3f5b9ee214a130e2c8ba30d29)) - -* ci: update version number ([`6e0c194`](https://github.com/agritheory/inventory_tools/commit/6e0c194235a19011b0c7db5adb8ed7e5954ba5eb)) - -* ci: add python semantic release ([`3382787`](https://github.com/agritheory/inventory_tools/commit/3382787d4726d7483a7243eafff03eb775d0ac3e)) - -### Feature - -* feat: based on item option ([`cc90229`](https://github.com/agritheory/inventory_tools/commit/cc90229b9ccf27cb5a872b24109dc7071f146802)) - -* feat: wip, make rfqs ([`c5a8867`](https://github.com/agritheory/inventory_tools/commit/c5a88673c3d57480a10ec68091e04a75488e18cb)) - -* feat: wip material demand options ([`bedd3d4`](https://github.com/agritheory/inventory_tools/commit/bedd3d42f299c73c1c1fa80c3a4928316d1428a2)) - -* feat: requires_rfq custom field, creation options in report ([`cd4ec42`](https://github.com/agritheory/inventory_tools/commit/cd4ec42e15fdbfa2cc24dc41b16562e74daf6124)) - -### Fix - -* fix: fix JS after adding draft PO column (#26) ([`42aefa9`](https://github.com/agritheory/inventory_tools/commit/42aefa9abab60962f923870a151d7bacbceba141)) - -### Unknown - -* Merge pull request #22 from agritheory/ci_fix - -ci: update remote name ([`946657b`](https://github.com/agritheory/inventory_tools/commit/946657b179d2a8ba6934c2df7ca5d83f9bb04f29)) - -* Merge pull request #21 from agritheory/py_sem_rel_14 - -ci: add python semantic release ([`13b41fa`](https://github.com/agritheory/inventory_tools/commit/13b41fad052f9c45e017b6fbac6897bdf38b7883)) - - -## v14.0.0 (2023-07-21) - -### Documentation - -* docs: wip material demand docs ([`6116a1b`](https://github.com/agritheory/inventory_tools/commit/6116a1b30b77565ff0470af32f8f59aa7a949786)) - -### Feature - -* feat: add column for draft PO amount ([`59d837b`](https://github.com/agritheory/inventory_tools/commit/59d837b1d3dbf4798d08618d033f732cad76cf1f)) - -* feat: create inventory tools settings when company is created ([`0121499`](https://github.com/agritheory/inventory_tools/commit/0121499bd99fa9ff5126b7432dd1d9a1d2816dd4)) - -* feat: create inventory tools settings when company is created ([`edff215`](https://github.com/agritheory/inventory_tools/commit/edff215f58ce8163da37436af893e1395164520c)) - -* feat: material demand PO creation ([`794f735`](https://github.com/agritheory/inventory_tools/commit/794f7352b27eb000ca96ece71c8081b69f519751)) - -* feat: add setting doctype ([`25a75de`](https://github.com/agritheory/inventory_tools/commit/25a75de2f1415ed78634d45c255438f1ed7a3ad1)) - -* feat: Initialize App ([`9e932fe`](https://github.com/agritheory/inventory_tools/commit/9e932fe49e70d5f2507d5900839c32f063a20898)) - -### Fix - -* fix: purchase order custom filed missing, carry price list from report to PO ([`4fe5ac8`](https://github.com/agritheory/inventory_tools/commit/4fe5ac84f52d656db3017af5e5a2a08111b2a729)) - -* fix: add back price list filter, fix schema ([`ceda857`](https://github.com/agritheory/inventory_tools/commit/ceda85797cc62a2d0e70e3a1135a88492f5c2cc0)) - -* fix: rebased v14 conflicts ([`b1614cb`](https://github.com/agritheory/inventory_tools/commit/b1614cb28a3f57d31c2056bf4e4506fd94a6e997)) - -* fix: supplier level de-selection and filtering ([`94140d0`](https://github.com/agritheory/inventory_tools/commit/94140d042a2e3fec79a56f0cacb86725dc2539b7)) - -* fix: module import name ([`ae290f8`](https://github.com/agritheory/inventory_tools/commit/ae290f8a392d9c5b3ea941244e68c8f1099728ef)) - -### Unknown - -* Merge pull request #20 from agritheory/material_demand - -Material Demand report fixes ([`7eb3c87`](https://github.com/agritheory/inventory_tools/commit/7eb3c877932a4d072ff56af23ad77958aba2fc36)) - -* Merge pull request #15 from agritheory/material_demand - -Material Demand ([`486fde6`](https://github.com/agritheory/inventory_tools/commit/486fde69cfdfa8810d93445ef4b32eb0753e799c)) - -* Merge branch 'version-14' into material_demand ([`9275dbf`](https://github.com/agritheory/inventory_tools/commit/9275dbf04f30a7391a0c003fff77cc5b105bd4cb)) - -* wip: material demand report improvements ([`d167804`](https://github.com/agritheory/inventory_tools/commit/d167804e90e10fc8299a49f6f0b90a512e93b5a3)) - -* wip: material demand ([`067b0d7`](https://github.com/agritheory/inventory_tools/commit/067b0d71dc372c35ac988556b20d13b9ab95f009)) - -* Merge pull request #16 from agritheory/settings_hook - -feat: create inventory tools settings when company is created ([`acc2b9c`](https://github.com/agritheory/inventory_tools/commit/acc2b9c640e1cb9eadf2e96060518a323ce34990)) - -* wip: material demand - -selection helpers look good except for supplier-level deselect, which toggles everything backwards ([`de7e09c`](https://github.com/agritheory/inventory_tools/commit/de7e09c4e04456fcd5d23fdbfa30c3a8a1933c28)) - -* wip: warehouse path ([`3ef9d3e`](https://github.com/agritheory/inventory_tools/commit/3ef9d3e7a30a98339f7d09c5ecba2e666e877b49)) - -* wip: material demand report improvements ([`c20379a`](https://github.com/agritheory/inventory_tools/commit/c20379aae9659fc1280f3c884bc888cce765116d)) - -* wip: material demand ([`3f50d5f`](https://github.com/agritheory/inventory_tools/commit/3f50d5f96b5b0a57993320e4f3c56034a490cd9a)) - -* wip: material demand ([`0cb8694`](https://github.com/agritheory/inventory_tools/commit/0cb869487fc576470f5ddb7f1b8f3b23f4cc1a57)) - -* Merge pull request #7 from agritheory/settings_doctype - -feat: add setting doctype ([`5285a99`](https://github.com/agritheory/inventory_tools/commit/5285a9967fc3615f16c7d4b06ac6f55589966975)) - -* Merge pull request #6 from agritheory/test_data_fixes - -fix: module import name ([`6edf7fb`](https://github.com/agritheory/inventory_tools/commit/6edf7fb0127648c90b0e3c203473681b8b964b63)) - -* initial commit ([`a09e1ed`](https://github.com/agritheory/inventory_tools/commit/a09e1ed6724ea49e39d5e208e6031283bf282f97)) - +* feat: allow user to bulk upload items with quantity to shoping cart + +* nit: variable and syntactical changes + +* fix: removed line by line order placing, optimised code, added enqueue + +* fix: minor cleanup + +--------- + +Co-authored-by: Rohan Bansal <rohan@agritheory.dev> ([`748a9bc`](https://github.com/agritheory/inventory_tools/commit/748a9bc85034094dcd60544fe2b822b67322fb44)) + +### Unknown + +* Aggregate and/or Split Quotations into multiple Sales Orders (#65) + +* feat: Quotation Demand + +* feat: hook + +* feat: settings for quotation demand + +* feat: fixes, SO validate_warehouse + +* feat: quotation demand tests + +* feat: documentation + +* feat: improvements + +* feat: improve tests + +* feat: total selected, price, draft so + +* feat: tests ([`6eceeb5`](https://github.com/agritheory/inventory_tools/commit/6eceeb5623856d659db1ffc3dd7a3ce352cd8000)) + + +## v14.4.0 (2024-04-25) + +### Ci + +* ci: add black to ci (#61) + +* ci: add black to ci + +* chore: black ([`db5a742`](https://github.com/agritheory/inventory_tools/commit/db5a7427f068d7005f8f07125d81f1430c49eb9b)) + +### Feature + +* feat: aggregate POs (#71) ([`5ff8fee`](https://github.com/agritheory/inventory_tools/commit/5ff8fee2ef356990e2dcda0d2db76d1b856a0685)) + +### Unknown + +* Material Demand Test (#64) + +* wip: material demand tests + +* test: material demand aggregation tests and fixes with and without warehouse + +* test: material demand tests and bug fixes + +* chore: add mypy types isntall + +* fix: remove duplicate function + +* tests: add pytest runner file + +* tests: add helper files + +* tests: correct app name + +* ci: fix site_config + +* ci: update action version to use node 20 + +* ci: hrms get-app + +* ci: add base branch sensitvie get-app + +* ci: add hrms to install + +* ci: add node 20 versions + +* ci: remove hrms from install-apps + +* ci: get-app for hrms + +* ci: update prettier and changed-files actions + +* ci: ad dhrms to apps.txt + +* ci: get-app for hrms again + +* ci: get-app for hrms only + +* ci: overrite erpnext install (hrms is tryign to install develop branch) + +* ci: add app name + +* ci: add repo to required apps + +* ci: try install hrms first with overwrite + +* ci: remove "install_apps" key from site_config + +* ci: remove required apps + +* feat: use query builder + +* ci: remove resolve deps + +* ci: fix install apps + +* test: fix manufacturing capacity test and report + +* test: cleanup uom test + +* test: fix error message assert + +* test: add ordering + +* fix: test + +* fix: use frappe function + +* fix: use frappe function + +--------- + +Co-authored-by: fproldan <franciscoproldan@gmail.com> ([`6f4f63f`](https://github.com/agritheory/inventory_tools/commit/6f4f63f22f3f7278e20c6aba9e5ef6a021ae03b2)) + +* Manufacturing capacity report (#57) + +* ci: update app in str(file path) code to more exact matching + +* chore: remove unused code + +* feat: add manufacturing capacity report + +* tests: start manufacturing capacity report tests + +* chore: uncomment formatting code + +* docs: add manufacturing capacity report documentation + +* fix: div by zero in parts can build calc + +* docs: update for calculation differences + +* fix: in stock qty to zero if none from query ([`2936cde`](https://github.com/agritheory/inventory_tools/commit/2936cde9aac6583edeb383d94d74142461cf243a)) + + +## v14.3.0 (2024-03-01) + +### Feature + +* feat: Alternative workstation in job card and operation (#56) + +* feat: New field and link filters to select alternative workstation + +* fix: add alternativ workstation in fixture + +* fix:change alternative workstation in fixture + +* change to error key function + +* fix: set validation on workstation if not operation + +* changes field name in testcase + +* fix: change a class base function to saperate function + +* added a searchfield in query + +* added a searchfield in query + +* added a searchfield in query + +* added a searchfield in query + +* added a searchfield in query + +* feat: validation to not allow default workstation in alternative + +* added comment on function ([`0788d3c`](https://github.com/agritheory/inventory_tools/commit/0788d3caa67ad7820a5a3cdfdc950c85bd6f0cd7)) + +### Unknown + +* Prompt Material Transfer upon Completion of Manufacturing Stock Entry (#51) + +* feat: wip stock entry next action + +* feat: improve message + +* fix: on_submit hook + +* fix: parameter hardcoded + +* feat: change wording ([`d1e126b`](https://github.com/agritheory/inventory_tools/commit/d1e126b8dbaf09370f6d4c173e24af33ac994bd7)) + + +## v14.2.0 (2024-02-01) + +### Feature + +* feat: manufacturing over/under production + +* feat: WIP Manufacturing Over/Under Production + +* feat: WIP Manufacturing Over/Under Production + +* feat: WIP Manufacturing Over/Under Production + +* fix: unused import + +* feat: override onload for work order + +* feat: oveeride get_pending_raw_materials + +* fix: allowed_qty in job card + +* fix: indentation + +* fix: import + +* fixes + +* wip: tests + +* feat: test_get_allowance_percentage + +* feat: test test_validate_finished_goods + +* fix: validate_job_card and test + +* fix: test ([`baeb469`](https://github.com/agritheory/inventory_tools/commit/baeb4690d42429a062595eb9058ddd2770b190c9)) + +### Unknown + +* Make Creation of Job Card(s) on Submit of Work Order configurable (#49) + +* feat: configurable creation of job card + +* feat: configurable creation of job card ([`5bf9486`](https://github.com/agritheory/inventory_tools/commit/5bf94860c58d81faccb1106828f16121c081871a)) + + +## v14.1.3 (2024-01-04) + +### Fix + +* fix: validate customizations (#35) + +* fix: validate customizations + +* fix: only install inventory tools customizations ([`e1d86a0`](https://github.com/agritheory/inventory_tools/commit/e1d86a0739e56f3b987b599c275644ee5c29fc0a)) + + +## v14.1.2 (2023-09-12) + +### Chore + +* chore: remove console.log ([`f82b590`](https://github.com/agritheory/inventory_tools/commit/f82b590d061608818170092f07e3da8d9153b756)) + +### Ci + +* ci: update release action user and email (#32) ([`4264bdd`](https://github.com/agritheory/inventory_tools/commit/4264bdde25c0bff1390923e7f18fce7c353844db)) + +### Fix + +* fix: make uom enforcement respond better to toggle on/off ([`3734cb4`](https://github.com/agritheory/inventory_tools/commit/3734cb42e880168bb4c4a71c67820da63857e0bf)) + +### Unknown + +* Merge pull request #33 from agritheory/uom_enforcement_fix + +fix: make uom enforcement respond better to toggle on/off ([`13ad883`](https://github.com/agritheory/inventory_tools/commit/13ad8832a346799563e0f7ae2f1b20c457d10d5c)) + + +## v14.1.1 (2023-08-30) + +### Fix + +* fix: add is_subcontracted check for additional validation/submit/cancel code ([`8182dac`](https://github.com/agritheory/inventory_tools/commit/8182dacfd35d2a2ee4c5ee94211cbfc7ac00abfd)) + +### Unknown + +* Merge pull request #30 from agritheory/fix_subc_validation + +fix: add is_subcontracted check for additional validation/submit/cancel code ([`c4e7b83`](https://github.com/agritheory/inventory_tools/commit/c4e7b83fd1700d08e8f711e10f1a77c81da0de32)) + + +## v14.1.0 (2023-08-24) + +### Chore + +* chore: update test data for erpnext codebase changes (#24) ([`b7dfc02`](https://github.com/agritheory/inventory_tools/commit/b7dfc02e228c4ebdca86000dac65d1a903640b15)) + +### Ci + +* ci: update remote name ([`021b8a4`](https://github.com/agritheory/inventory_tools/commit/021b8a47355cb9028bac7ac8e60d224247d5b0e8)) + +* ci: update version number ([`9d82150`](https://github.com/agritheory/inventory_tools/commit/9d821506af9d6eb72e3bfb1345ac652aa86896dc)) + +* ci: add python semantic release ([`703803d`](https://github.com/agritheory/inventory_tools/commit/703803df7949fb0cb43699482425ec31595dd1b9)) + +### Documentation + +* docs: update material demand section for expanded functionality ([`1af88f6`](https://github.com/agritheory/inventory_tools/commit/1af88f6d06fdc8e6908381f9dd9011fe470dd9d7)) + +### Feature + +* feat: select email template ([`02196e3`](https://github.com/agritheory/inventory_tools/commit/02196e37c7234982c5dafda9e814117d374565a9)) + +### Fix + +* fix: blank email template for PO; skip supplier-only rows for RFQ ([`2a0e8cd`](https://github.com/agritheory/inventory_tools/commit/2a0e8cd6c6aefdd1a0d7b978652f97ddc755523f)) + +* fix: fix JS after adding draft PO column (#26) ([`e0d3229`](https://github.com/agritheory/inventory_tools/commit/e0d322950e87dcf09f13441859e273a0e44a1192)) + +### Unknown + +* Merge pull request #23 from agritheory/issue_19 + +Allow Creation of RFQ from Material Demand report ([`8a0e350`](https://github.com/agritheory/inventory_tools/commit/8a0e35024968ce5a0f6da05e71f62c091bf2b38f)) + +* Work Order Subcontracting (#13) + +* tests: update test data for additional manufacturing workflow + +* feat: work order subcontracting validations + +* tests: add valuation rate for subcontracted item + +* feat: start wo subcontracting feat + +* feat: make subcontracting section visible by check and settings + +* feat: add ste detail paid field and new pi cols + +* feat: setup hooks and custom po + +* tests: update data for default supplier and price lists + +* feat: include doctype js + +* feat: add work order customizations + +* feat: add purchase order customizations + +* feat: update purchase invoice customizations + +* feat: remove unused code blocks + +* fix: add module to json + +* fix: update custom doc path + +* feat: consolidate custom PI code and modularize class functions + +* feat: combine and refactor PO code + +* feat: update server function paths + +* feat: add BOM field default + +* feat: update to use BOM field vs Item for is_subcontracted + +* feat: code cleanup and refactoring for BOM field + +* feat: update for uom conversion and new svc item + +* fix: move UOM conversions to item + +* add todos in JS + +* feat: rewire item adjustments for conversion factor + +* wip: integrate with production plan + +* feat: add supplier field in WO, allow selection of supplier in dialog + +* chore: add comment explaining precision code + +* wip: subcontractor workflow + +* feat: subcontracting workflow with correct warehouses + +* feat: show/hide subcontracting columns + +* feat: colorize fetach stock entries button + +* fix: text artifacts, new PO errors + +* feat: fetch supplier warehouse, added connectiosn to PI and PO from WO + +* feat: add filters and looks to both PI and PO + +* fix: monkey patch validate_item_details + +* feat: remove buttons and update stockfield in WO subc workflow + +* Enforce UOMs to those that exist in the Item's conversion detail (#27) + +* wip: uom restricted query + +* feat: refactor UOM enforcement validation to be hookable + +* docs: add docs for UOM enforcement + +* tests: fix test logger problem, add xfail uom test + +* Warehouse path (#25) + +* wip: warehouse path + +* wip: warehouse path + +* wip: warehouse path feature + +* feat: warehouse path builder + +* feat: undo query when not configured; setup tweaks + +* chore: update test data for erpnext codebase changes (#24) + +* wip: warehouse path feature + +* wip: test setup + +* chore: update yarn + +* tests: trying to defaeat logger problem + +* test: fix conftest logger issue + +* docs: add docs for warehouse path + +* chore: union types for whitelisted function + +--------- + +Co-authored-by: Heather Kusmierz <heather.kusmierz@gmail.com> + +* tests: test cadence (#28) + +* fix: no cancelled PO in se query, code clean up + +* chore: add comment to explain monkey patch rationale + +--------- + +Co-authored-by: Tyler Matteson <tyler@agritheory.com> ([`ac11c1d`](https://github.com/agritheory/inventory_tools/commit/ac11c1df4daad2189916ca9841480aa1796e42e3)) + +* Merge branch 'version-14' into issue_19 ([`ee0a27f`](https://github.com/agritheory/inventory_tools/commit/ee0a27f0f03a8e3c9e9fa54011d02e44554b8bbb)) + +* Documentation (#29) + +* docs: add index page + +* docs: add screen shots and workflow + +* docs: add screen shots, text edits + +* docs: add example data page + +* docs: add placeholder pages + +* docs: add subcontracting via WO section + +* docs: edits, conform text conventions ([`2fc980d`](https://github.com/agritheory/inventory_tools/commit/2fc980d41105759cffa33e610b779b6d464cf24c)) + +* tests: test cadence (#28) ([`6b5bd47`](https://github.com/agritheory/inventory_tools/commit/6b5bd47089fb2f8a09159635e618425743cc9dff)) + +* Warehouse path (#25) + +* wip: warehouse path + +* wip: warehouse path + +* wip: warehouse path feature + +* feat: warehouse path builder + +* feat: undo query when not configured; setup tweaks + +* chore: update test data for erpnext codebase changes (#24) + +* wip: warehouse path feature + +* wip: test setup + +* chore: update yarn + +* tests: trying to defaeat logger problem + +* test: fix conftest logger issue + +* docs: add docs for warehouse path + +* chore: union types for whitelisted function + +--------- + +Co-authored-by: Heather Kusmierz <heather.kusmierz@gmail.com> ([`370dd6f`](https://github.com/agritheory/inventory_tools/commit/370dd6f9789156ebcbbe7b111d891a74731a477b)) + +* Enforce UOMs to those that exist in the Item's conversion detail (#27) + +* wip: uom restricted query + +* feat: refactor UOM enforcement validation to be hookable + +* docs: add docs for UOM enforcement + +* tests: fix test logger problem, add xfail uom test ([`d4c145a`](https://github.com/agritheory/inventory_tools/commit/d4c145a94d8402fa441619289b4cc6438b7d5c45)) + +* Documentation (#29) + +* docs: add index page + +* docs: add screen shots and workflow + +* docs: add screen shots, text edits + +* docs: add example data page + +* docs: add placeholder pages + +* docs: add subcontracting via WO section + +* docs: edits, conform text conventions ([`198e110`](https://github.com/agritheory/inventory_tools/commit/198e110ab0c5461b9c46925fc05af351151abd38)) + +* tests: test cadence (#28) ([`b91e024`](https://github.com/agritheory/inventory_tools/commit/b91e0246f6e384f40685af40d3a249daa9d03a8c)) + +* Warehouse path (#25) + +* wip: warehouse path + +* wip: warehouse path + +* wip: warehouse path feature + +* feat: warehouse path builder + +* feat: undo query when not configured; setup tweaks + +* chore: update test data for erpnext codebase changes (#24) + +* wip: warehouse path feature + +* wip: test setup + +* chore: update yarn + +* tests: trying to defaeat logger problem + +* test: fix conftest logger issue + +* docs: add docs for warehouse path + +* chore: union types for whitelisted function + +--------- + +Co-authored-by: Heather Kusmierz <heather.kusmierz@gmail.com> ([`e3fb9c7`](https://github.com/agritheory/inventory_tools/commit/e3fb9c7f2a8ed3c42f4cb47078086bcdd60f91c7)) + +* Enforce UOMs to those that exist in the Item's conversion detail (#27) + +* wip: uom restricted query + +* feat: refactor UOM enforcement validation to be hookable + +* docs: add docs for UOM enforcement + +* tests: fix test logger problem, add xfail uom test ([`65d42e1`](https://github.com/agritheory/inventory_tools/commit/65d42e126d81f3ed1b98178f7b6c68c6a070986e)) + + +## v14.0.1 (2023-08-10) + +### Chore + +* chore: update test data for erpnext codebase changes (#24) ([`48160aa`](https://github.com/agritheory/inventory_tools/commit/48160aa27f5d0deb3be5e6e55f16d35fd92ae086)) + +### Ci + +* ci: update remote name ([`218eb06`](https://github.com/agritheory/inventory_tools/commit/218eb06a6a4a2ac3f5b9ee214a130e2c8ba30d29)) + +* ci: update version number ([`6e0c194`](https://github.com/agritheory/inventory_tools/commit/6e0c194235a19011b0c7db5adb8ed7e5954ba5eb)) + +* ci: add python semantic release ([`3382787`](https://github.com/agritheory/inventory_tools/commit/3382787d4726d7483a7243eafff03eb775d0ac3e)) + +### Feature + +* feat: based on item option ([`cc90229`](https://github.com/agritheory/inventory_tools/commit/cc90229b9ccf27cb5a872b24109dc7071f146802)) + +* feat: wip, make rfqs ([`c5a8867`](https://github.com/agritheory/inventory_tools/commit/c5a88673c3d57480a10ec68091e04a75488e18cb)) + +* feat: wip material demand options ([`bedd3d4`](https://github.com/agritheory/inventory_tools/commit/bedd3d42f299c73c1c1fa80c3a4928316d1428a2)) + +* feat: requires_rfq custom field, creation options in report ([`cd4ec42`](https://github.com/agritheory/inventory_tools/commit/cd4ec42e15fdbfa2cc24dc41b16562e74daf6124)) + +### Fix + +* fix: fix JS after adding draft PO column (#26) ([`42aefa9`](https://github.com/agritheory/inventory_tools/commit/42aefa9abab60962f923870a151d7bacbceba141)) + +### Unknown + +* Merge pull request #22 from agritheory/ci_fix + +ci: update remote name ([`946657b`](https://github.com/agritheory/inventory_tools/commit/946657b179d2a8ba6934c2df7ca5d83f9bb04f29)) + +* Merge pull request #21 from agritheory/py_sem_rel_14 + +ci: add python semantic release ([`13b41fa`](https://github.com/agritheory/inventory_tools/commit/13b41fad052f9c45e017b6fbac6897bdf38b7883)) + + +## v14.0.0 (2023-07-21) + +### Documentation + +* docs: wip material demand docs ([`6116a1b`](https://github.com/agritheory/inventory_tools/commit/6116a1b30b77565ff0470af32f8f59aa7a949786)) + +### Feature + +* feat: add column for draft PO amount ([`59d837b`](https://github.com/agritheory/inventory_tools/commit/59d837b1d3dbf4798d08618d033f732cad76cf1f)) + +* feat: create inventory tools settings when company is created ([`0121499`](https://github.com/agritheory/inventory_tools/commit/0121499bd99fa9ff5126b7432dd1d9a1d2816dd4)) + +* feat: create inventory tools settings when company is created ([`edff215`](https://github.com/agritheory/inventory_tools/commit/edff215f58ce8163da37436af893e1395164520c)) + +* feat: material demand PO creation ([`794f735`](https://github.com/agritheory/inventory_tools/commit/794f7352b27eb000ca96ece71c8081b69f519751)) + +* feat: add setting doctype ([`25a75de`](https://github.com/agritheory/inventory_tools/commit/25a75de2f1415ed78634d45c255438f1ed7a3ad1)) + +* feat: Initialize App ([`9e932fe`](https://github.com/agritheory/inventory_tools/commit/9e932fe49e70d5f2507d5900839c32f063a20898)) + +### Fix + +* fix: purchase order custom filed missing, carry price list from report to PO ([`4fe5ac8`](https://github.com/agritheory/inventory_tools/commit/4fe5ac84f52d656db3017af5e5a2a08111b2a729)) + +* fix: add back price list filter, fix schema ([`ceda857`](https://github.com/agritheory/inventory_tools/commit/ceda85797cc62a2d0e70e3a1135a88492f5c2cc0)) + +* fix: rebased v14 conflicts ([`b1614cb`](https://github.com/agritheory/inventory_tools/commit/b1614cb28a3f57d31c2056bf4e4506fd94a6e997)) + +* fix: supplier level de-selection and filtering ([`94140d0`](https://github.com/agritheory/inventory_tools/commit/94140d042a2e3fec79a56f0cacb86725dc2539b7)) + +* fix: module import name ([`ae290f8`](https://github.com/agritheory/inventory_tools/commit/ae290f8a392d9c5b3ea941244e68c8f1099728ef)) + +### Unknown + +* Merge pull request #20 from agritheory/material_demand + +Material Demand report fixes ([`7eb3c87`](https://github.com/agritheory/inventory_tools/commit/7eb3c877932a4d072ff56af23ad77958aba2fc36)) + +* Merge pull request #15 from agritheory/material_demand + +Material Demand ([`486fde6`](https://github.com/agritheory/inventory_tools/commit/486fde69cfdfa8810d93445ef4b32eb0753e799c)) + +* Merge branch 'version-14' into material_demand ([`9275dbf`](https://github.com/agritheory/inventory_tools/commit/9275dbf04f30a7391a0c003fff77cc5b105bd4cb)) + +* wip: material demand report improvements ([`d167804`](https://github.com/agritheory/inventory_tools/commit/d167804e90e10fc8299a49f6f0b90a512e93b5a3)) + +* wip: material demand ([`067b0d7`](https://github.com/agritheory/inventory_tools/commit/067b0d71dc372c35ac988556b20d13b9ab95f009)) + +* Merge pull request #16 from agritheory/settings_hook + +feat: create inventory tools settings when company is created ([`acc2b9c`](https://github.com/agritheory/inventory_tools/commit/acc2b9c640e1cb9eadf2e96060518a323ce34990)) + +* wip: material demand + +selection helpers look good except for supplier-level deselect, which toggles everything backwards ([`de7e09c`](https://github.com/agritheory/inventory_tools/commit/de7e09c4e04456fcd5d23fdbfa30c3a8a1933c28)) + +* wip: warehouse path ([`3ef9d3e`](https://github.com/agritheory/inventory_tools/commit/3ef9d3e7a30a98339f7d09c5ecba2e666e877b49)) + +* wip: material demand report improvements ([`c20379a`](https://github.com/agritheory/inventory_tools/commit/c20379aae9659fc1280f3c884bc888cce765116d)) + +* wip: material demand ([`3f50d5f`](https://github.com/agritheory/inventory_tools/commit/3f50d5f96b5b0a57993320e4f3c56034a490cd9a)) + +* wip: material demand ([`0cb8694`](https://github.com/agritheory/inventory_tools/commit/0cb869487fc576470f5ddb7f1b8f3b23f4cc1a57)) + +* Merge pull request #7 from agritheory/settings_doctype + +feat: add setting doctype ([`5285a99`](https://github.com/agritheory/inventory_tools/commit/5285a9967fc3615f16c7d4b06ac6f55589966975)) + +* Merge pull request #6 from agritheory/test_data_fixes + +fix: module import name ([`6edf7fb`](https://github.com/agritheory/inventory_tools/commit/6edf7fb0127648c90b0e3c203473681b8b964b63)) + +* initial commit ([`a09e1ed`](https://github.com/agritheory/inventory_tools/commit/a09e1ed6724ea49e39d5e208e6031283bf282f97)) + diff --git a/inventory_tools/docs/faceted_search.md b/inventory_tools/docs/faceted_search.md index a30111b..53e1e6f 100644 --- a/inventory_tools/docs/faceted_search.md +++ b/inventory_tools/docs/faceted_search.md @@ -1,3 +1,6 @@ + + # Faceted Search diff --git a/inventory_tools/docs/index.md b/inventory_tools/docs/index.md index 2a39846..c5348ee 100644 --- a/inventory_tools/docs/index.md +++ b/inventory_tools/docs/index.md @@ -1,3 +1,6 @@ + + # Inventory Tools Documentation The Inventory Tools application enhances and extends inventory-related functionality and workflows in ERPNext. It includes the following features: diff --git a/inventory_tools/hooks.py b/inventory_tools/hooks.py index 5887e1d..fa363cb 100644 --- a/inventory_tools/hooks.py +++ b/inventory_tools/hooks.py @@ -9,7 +9,7 @@ app_description = "Inventory Tools" app_email = "support@agritheory.dev" app_license = "MIT" -required_apps = ["erpnext", "hrms"] +required_apps = ["erpnext", "hrms", "webshop"] # Includes in # ------------------ diff --git a/inventory_tools/inventory_tools/boot.py b/inventory_tools/inventory_tools/boot.py index 1a20d32..01dda3e 100644 --- a/inventory_tools/inventory_tools/boot.py +++ b/inventory_tools/inventory_tools/boot.py @@ -1,8 +1,11 @@ -import frappe - - -def boot_session(bootinfo): - bootinfo.inventory_tools_settings = {} - for company in frappe.get_all("Inventory Tools Settings", pluck="company"): - settings = frappe.get_doc("Inventory Tools Settings", company) - bootinfo.inventory_tools_settings[company] = settings +# Copyright (c) 2024, AgriTheory and contributors +# For license information, please see license.txt + +import frappe + + +def boot_session(bootinfo): + bootinfo.inventory_tools_settings = {} + for company in frappe.get_all("Inventory Tools Settings", pluck="company"): + settings = frappe.get_doc("Inventory Tools Settings", company) + bootinfo.inventory_tools_settings[company] = settings diff --git a/inventory_tools/inventory_tools/custom/color.json b/inventory_tools/inventory_tools/custom/color.json index f5075d8..f0b78c0 100644 --- a/inventory_tools/inventory_tools/custom/color.json +++ b/inventory_tools/inventory_tools/custom/color.json @@ -1,70 +1,57 @@ { - "custom_fields": [ - { - "_assign": null, - "_comments": null, - "_liked_by": null, - "_user_tags": null, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "collapsible_depends_on": null, - "columns": 0, - "creation": "2024-02-22 10:20:21.468031", - "default": null, - "depends_on": null, - "description": null, - "docstatus": 0, - "dt": "Color", - "fetch_from": null, - "fetch_if_empty": 0, - "fieldname": "image", - "fieldtype": "Attach", - "hidden": 0, - "hide_border": 0, - "hide_days": 0, - "hide_seconds": 0, - "idx": 1, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_preview": 0, - "in_standard_filter": 0, - "insert_after": "color", - "is_system_generated": 0, - "is_virtual": 0, - "label": "Image", - "length": 0, - "mandatory_depends_on": null, - "modified": "2024-02-22 10:20:21.468031", - "modified_by": "Administrator", - "module": "Inventory Tools", - "name": "Color-image", - "no_copy": 0, - "non_negative": 0, - "options": null, - "owner": "Administrator", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "print_width": null, - "read_only": 0, - "read_only_depends_on": null, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "sort_options": 0, - "translatable": 0, - "unique": 0, - "width": null - } - ], - "custom_perms": [], - "doctype": "Color", - "links": [], - "property_setters": [], - "sync_on_migrate": 1 -} \ No newline at end of file + "custom_fields": [ + { + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "creation": "2024-02-22 10:20:21.468031", + "default": null, + "docstatus": 0, + "dt": "Color", + "fetch_if_empty": 0, + "fieldname": "image", + "fieldtype": "Attach", + "hidden": 0, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 1, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_preview": 0, + "in_standard_filter": 0, + "insert_after": "color", + "is_system_generated": 0, + "is_virtual": 0, + "label": "Image", + "length": 0, + "modified": "2024-02-22 10:20:21.468031", + "modified_by": "Administrator", + "module": "Inventory Tools", + "name": "Color-image", + "no_copy": 0, + "non_negative": 0, + "owner": "Administrator", + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "sort_options": 0, + "translatable": 0, + "unique": 0 + } + ], + "custom_perms": [], + "doctype": "Color", + "links": [], + "property_setters": [], + "sync_on_migrate": 1 +} diff --git a/inventory_tools/inventory_tools/custom/operation.json b/inventory_tools/inventory_tools/custom/operation.json index 30039ed..757da24 100644 --- a/inventory_tools/inventory_tools/custom/operation.json +++ b/inventory_tools/inventory_tools/custom/operation.json @@ -1,75 +1,4 @@ { -<<<<<<< HEAD - "custom_fields": [ - { - "_assign": null, - "_comments": null, - "_liked_by": null, - "_user_tags": null, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "collapsible_depends_on": null, - "columns": 0, - "creation": "2024-02-16 05:04:42.422068", - "default": null, - "depends_on": null, - "description": null, - "docstatus": 0, - "dt": "Operation", - "fetch_from": null, - "fetch_if_empty": 0, - "fieldname": "alternative_workstations", - "fieldtype": "Table MultiSelect", - "hidden": 0, - "hide_border": 0, - "hide_days": 0, - "hide_seconds": 0, - "idx": 1, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_preview": 0, - "in_standard_filter": 0, - "insert_after": "workstation", - "is_system_generated": 0, - "is_virtual": 0, - "label": "Alternative Workstations", - "length": 0, - "mandatory_depends_on": null, - "modified": "2024-02-16 05:04:42.422068", - "modified_by": "Administrator", - "module": "Inventory Tools", - "name": "Operation-alternative_workstations", - "no_copy": 0, - "non_negative": 0, - "options": "Alternative Workstation", - "owner": "Administrator", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "print_width": null, - "read_only": 0, - "read_only_depends_on": null, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "sort_options": 0, - "translatable": 0, - "unique": 0, - "width": null - } - ], - "custom_perms": [], - "doctype": "Operation", - "links": [], - "property_setters": [], - "sync_on_migrate": 1 -} -======= "custom_fields": [ { "allow_in_quick_entry": 0, @@ -127,4 +56,3 @@ "property_setters": [], "sync_on_migrate": 1 } ->>>>>>> 12d5afa2ce39627719b130a5ed0e5ce879c818f6 diff --git a/inventory_tools/inventory_tools/doctype/specification/__init__.py b/inventory_tools/inventory_tools/doctype/specification/__init__.py index e69de29..6b9109e 100644 --- a/inventory_tools/inventory_tools/doctype/specification/__init__.py +++ b/inventory_tools/inventory_tools/doctype/specification/__init__.py @@ -0,0 +1,2 @@ +# Copyright (c) 2024, AgriTheory and contributors +# For license information, please see license.txt diff --git a/inventory_tools/inventory_tools/doctype/specification/specification.json b/inventory_tools/inventory_tools/doctype/specification/specification.json index 5fb3ca5..e6faa4b 100644 --- a/inventory_tools/inventory_tools/doctype/specification/specification.json +++ b/inventory_tools/inventory_tools/doctype/specification/specification.json @@ -1,133 +1,125 @@ { - "actions": [], - "allow_rename": 1, - "autoname": "prompt", - "creation": "2023-11-13 16:45:20.279292", - "default_view": "List", - "doctype": "DocType", - "editable_grid": 1, - "engine": "InnoDB", - "field_order": [ - "title", - "dt", - "enabled", - "column_break_conqh", - "apply_on", - "section_break_5", - "attributes" - ], - "fields": [ - { - "fieldname": "dt", - "fieldtype": "Link", - "label": "DocType", - "options": "DocType" - }, - { - "default": "0", - "fieldname": "enabled", - "fieldtype": "Check", - "label": "Enabled" - }, - { - "fieldname": "apply_on", - "fieldtype": "Dynamic Link", - "label": "Apply On", - "options": "dt" - }, - { - "fieldname": "column_break_conqh", - "fieldtype": "Column Break" - }, - { - "fieldname": "section_break_5", - "fieldtype": "Section Break", - "label": "Attributes" - }, - { - "fieldname": "attributes", - "fieldtype": "Table", - "options": "Specification Attribute" - }, - { - "fieldname": "title", - "fieldtype": "Data", - "hidden": 1, - "label": "Title" - } - ], - "index_web_pages_for_search": 1, - "links": [], - "modified": "2024-06-08 11:21:58.918995", - "modified_by": "Administrator", - "module": "Inventory Tools", - "name": "Specification", - "naming_rule": "Set by user", - "owner": "Administrator", - "permissions": [ - { - "create": 1, - "delete": 1, - "email": 1, - "export": 1, - "print": 1, - "read": 1, - "report": 1, - "role": "System Manager", - "share": 1, - "write": 1 - }, - { - "create": 1, - "delete": 1, - "email": 1, - "export": 1, - "print": 1, - "read": 1, - "report": 1, - "role": "Item Manager", - "share": 1, - "write": 1 - }, - { - "create": 1, - "delete": 1, - "email": 1, - "export": 1, - "print": 1, - "read": 1, - "report": 1, - "role": "Website Manager", - "share": 1, - "write": 1 - }, - { - "create": 1, - "delete": 1, - "email": 1, - "export": 1, - "print": 1, - "read": 1, - "report": 1, - "role": "Purchase Master Manager", - "share": 1, - "write": 1 - }, - { - "create": 1, - "delete": 1, - "email": 1, - "export": 1, - "print": 1, - "read": 1, - "report": 1, - "role": "Sales Master Manager", - "share": 1, - "write": 1 - } - ], - "sort_field": "modified", - "sort_order": "DESC", - "states": [], - "title_field": "title" -} \ No newline at end of file + "actions": [], + "allow_rename": 1, + "autoname": "prompt", + "creation": "2023-11-13 16:45:20.279292", + "default_view": "List", + "doctype": "DocType", + "editable_grid": 1, + "engine": "InnoDB", + "field_order": ["title", "dt", "enabled", "column_break_conqh", "apply_on", "section_break_5", "attributes"], + "fields": [ + { + "fieldname": "dt", + "fieldtype": "Link", + "label": "DocType", + "options": "DocType" + }, + { + "default": "0", + "fieldname": "enabled", + "fieldtype": "Check", + "label": "Enabled" + }, + { + "fieldname": "apply_on", + "fieldtype": "Dynamic Link", + "label": "Apply On", + "options": "dt" + }, + { + "fieldname": "column_break_conqh", + "fieldtype": "Column Break" + }, + { + "fieldname": "section_break_5", + "fieldtype": "Section Break", + "label": "Attributes" + }, + { + "fieldname": "attributes", + "fieldtype": "Table", + "options": "Specification Attribute" + }, + { + "fieldname": "title", + "fieldtype": "Data", + "hidden": 1, + "label": "Title" + } + ], + "index_web_pages_for_search": 1, + "links": [], + "modified": "2024-06-08 11:21:58.918995", + "modified_by": "Administrator", + "module": "Inventory Tools", + "name": "Specification", + "naming_rule": "Set by user", + "owner": "Administrator", + "permissions": [ + { + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "System Manager", + "share": 1, + "write": 1 + }, + { + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "Item Manager", + "share": 1, + "write": 1 + }, + { + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "Website Manager", + "share": 1, + "write": 1 + }, + { + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "Purchase Master Manager", + "share": 1, + "write": 1 + }, + { + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "Sales Master Manager", + "share": 1, + "write": 1 + } + ], + "sort_field": "modified", + "sort_order": "DESC", + "states": [], + "title_field": "title" +} diff --git a/inventory_tools/inventory_tools/doctype/specification_attribute/__init__.py b/inventory_tools/inventory_tools/doctype/specification_attribute/__init__.py index e69de29..6b9109e 100644 --- a/inventory_tools/inventory_tools/doctype/specification_attribute/__init__.py +++ b/inventory_tools/inventory_tools/doctype/specification_attribute/__init__.py @@ -0,0 +1,2 @@ +# Copyright (c) 2024, AgriTheory and contributors +# For license information, please see license.txt diff --git a/inventory_tools/inventory_tools/doctype/specification_attribute/specification_attribute.json b/inventory_tools/inventory_tools/doctype/specification_attribute/specification_attribute.json index ee39ba8..73ea1c0 100644 --- a/inventory_tools/inventory_tools/doctype/specification_attribute/specification_attribute.json +++ b/inventory_tools/inventory_tools/doctype/specification_attribute/specification_attribute.json @@ -1,94 +1,94 @@ { - "actions": [], - "creation": "2023-11-13 16:49:36.888483", - "doctype": "DocType", - "document_type": "Setup", - "engine": "InnoDB", - "field_order": [ - "attribute_name", - "numeric_values", - "date_values", - "required", - "column_break_k0wzm", - "applied_on", - "field", - "section_break_lbzwl", - "component" - ], - "fields": [ - { - "columns": 1, - "fieldname": "attribute_name", - "fieldtype": "Data", - "in_list_view": 1, - "label": "Attribute Name", - "reqd": 1, - "unique": 1 - }, - { - "columns": 1, - "default": "0", - "depends_on": "eval: !doc.date_values", - "fieldname": "numeric_values", - "fieldtype": "Check", - "label": "Numeric Values" - }, - { - "fieldname": "column_break_k0wzm", - "fieldtype": "Column Break" - }, - { - "default": "0", - "fieldname": "required", - "fieldtype": "Check", - "hidden": 1, - "label": "Required" - }, - { - "columns": 2, - "fieldname": "field", - "fieldtype": "Select", - "in_list_view": 1, - "label": "Field" - }, - { - "columns": 2, - "fieldname": "applied_on", - "fieldtype": "Link", - "in_list_view": 1, - "label": "Applied On", - "options": "DocType" - }, - { - "fieldname": "section_break_lbzwl", - "fieldtype": "Section Break" - }, - { - "fieldname": "component", - "fieldtype": "Select", - "label": "Component", - "options": "AttributeFilter\nFacetedSearchColorPicker\nFacetedSearchDateRange\nFacetedSearchNumericRange" - }, - { - "default": "0", - "depends_on": "eval: !doc.numeric_values", - "fieldname": "date_values", - "fieldtype": "Check", - "label": "Date Values" - } - ], - "icon": "fa fa-edit", - "index_web_pages_for_search": 1, - "istable": 1, - "links": [], - "modified": "2024-04-11 07:50:09.799568", - "modified_by": "Administrator", - "module": "Inventory Tools", - "name": "Specification Attribute", - "owner": "Administrator", - "permissions": [], - "sort_field": "modified", - "sort_order": "DESC", - "states": [], - "track_changes": 1 -} \ No newline at end of file + "actions": [], + "creation": "2023-11-13 16:49:36.888483", + "doctype": "DocType", + "document_type": "Setup", + "engine": "InnoDB", + "field_order": [ + "attribute_name", + "numeric_values", + "date_values", + "required", + "column_break_k0wzm", + "applied_on", + "field", + "section_break_lbzwl", + "component" + ], + "fields": [ + { + "columns": 1, + "fieldname": "attribute_name", + "fieldtype": "Data", + "in_list_view": 1, + "label": "Attribute Name", + "reqd": 1, + "unique": 1 + }, + { + "columns": 1, + "default": "0", + "depends_on": "eval: !doc.date_values", + "fieldname": "numeric_values", + "fieldtype": "Check", + "label": "Numeric Values" + }, + { + "fieldname": "column_break_k0wzm", + "fieldtype": "Column Break" + }, + { + "default": "0", + "fieldname": "required", + "fieldtype": "Check", + "hidden": 1, + "label": "Required" + }, + { + "columns": 2, + "fieldname": "field", + "fieldtype": "Select", + "in_list_view": 1, + "label": "Field" + }, + { + "columns": 2, + "fieldname": "applied_on", + "fieldtype": "Link", + "in_list_view": 1, + "label": "Applied On", + "options": "DocType" + }, + { + "fieldname": "section_break_lbzwl", + "fieldtype": "Section Break" + }, + { + "fieldname": "component", + "fieldtype": "Select", + "label": "Component", + "options": "AttributeFilter\nFacetedSearchColorPicker\nFacetedSearchDateRange\nFacetedSearchNumericRange" + }, + { + "default": "0", + "depends_on": "eval: !doc.numeric_values", + "fieldname": "date_values", + "fieldtype": "Check", + "label": "Date Values" + } + ], + "icon": "fa fa-edit", + "index_web_pages_for_search": 1, + "istable": 1, + "links": [], + "modified": "2024-04-11 07:50:09.799568", + "modified_by": "Administrator", + "module": "Inventory Tools", + "name": "Specification Attribute", + "owner": "Administrator", + "permissions": [], + "sort_field": "modified", + "sort_order": "DESC", + "states": [], + "track_changes": 1 +} diff --git a/inventory_tools/inventory_tools/doctype/specification_value/__init__.py b/inventory_tools/inventory_tools/doctype/specification_value/__init__.py index e69de29..6b9109e 100644 --- a/inventory_tools/inventory_tools/doctype/specification_value/__init__.py +++ b/inventory_tools/inventory_tools/doctype/specification_value/__init__.py @@ -0,0 +1,2 @@ +# Copyright (c) 2024, AgriTheory and contributors +# For license information, please see license.txt diff --git a/inventory_tools/inventory_tools/doctype/specification_value/specification_value.json b/inventory_tools/inventory_tools/doctype/specification_value/specification_value.json index 3836668..2101597 100644 --- a/inventory_tools/inventory_tools/doctype/specification_value/specification_value.json +++ b/inventory_tools/inventory_tools/doctype/specification_value/specification_value.json @@ -1,96 +1,89 @@ { - "actions": [], - "allow_rename": 1, - "creation": "2023-11-14 16:01:49.101184", - "default_view": "List", - "doctype": "DocType", - "editable_grid": 1, - "engine": "InnoDB", - "field_order": [ - "reference_doctype", - "reference_name", - "specification", - "field", - "attribute", - "value" - ], - "fields": [ - { - "fieldname": "attribute", - "fieldtype": "Data", - "in_list_view": 1, - "in_standard_filter": 1, - "label": "Attribute", - "read_only": 1, - "reqd": 1 - }, - { - "fieldname": "value", - "fieldtype": "Data", - "in_list_view": 1, - "in_standard_filter": 1, - "label": "Value", - "reqd": 1 - }, - { - "fieldname": "reference_doctype", - "fieldtype": "Link", - "in_list_view": 1, - "in_standard_filter": 1, - "label": "Reference Doctype", - "options": "DocType", - "read_only": 1, - "reqd": 1 - }, - { - "fieldname": "reference_name", - "fieldtype": "Dynamic Link", - "in_list_view": 1, - "in_standard_filter": 1, - "label": "Reference Name", - "options": "reference_doctype", - "read_only": 1, - "reqd": 1 - }, - { - "fieldname": "field", - "fieldtype": "Data", - "in_list_view": 1, - "in_standard_filter": 1, - "label": "Field", - "read_only": 1 - }, - { - "fieldname": "specification", - "fieldtype": "Link", - "label": "Specification", - "options": "Specification", - "reqd": 1 - } - ], - "index_web_pages_for_search": 1, - "links": [], - "modified": "2024-06-08 11:46:12.702788", - "modified_by": "Administrator", - "module": "Inventory Tools", - "name": "Specification Value", - "owner": "Administrator", - "permissions": [ - { - "create": 1, - "delete": 1, - "email": 1, - "export": 1, - "print": 1, - "read": 1, - "report": 1, - "role": "System Manager", - "share": 1, - "write": 1 - } - ], - "sort_field": "modified", - "sort_order": "DESC", - "states": [], - "title_field": "value" -} \ No newline at end of file + "actions": [], + "allow_rename": 1, + "creation": "2023-11-14 16:01:49.101184", + "default_view": "List", + "doctype": "DocType", + "editable_grid": 1, + "engine": "InnoDB", + "field_order": ["reference_doctype", "reference_name", "specification", "field", "attribute", "value"], + "fields": [ + { + "fieldname": "attribute", + "fieldtype": "Data", + "in_list_view": 1, + "in_standard_filter": 1, + "label": "Attribute", + "read_only": 1, + "reqd": 1 + }, + { + "fieldname": "value", + "fieldtype": "Data", + "in_list_view": 1, + "in_standard_filter": 1, + "label": "Value", + "reqd": 1 + }, + { + "fieldname": "reference_doctype", + "fieldtype": "Link", + "in_list_view": 1, + "in_standard_filter": 1, + "label": "Reference Doctype", + "options": "DocType", + "read_only": 1, + "reqd": 1 + }, + { + "fieldname": "reference_name", + "fieldtype": "Dynamic Link", + "in_list_view": 1, + "in_standard_filter": 1, + "label": "Reference Name", + "options": "reference_doctype", + "read_only": 1, + "reqd": 1 + }, + { + "fieldname": "field", + "fieldtype": "Data", + "in_list_view": 1, + "in_standard_filter": 1, + "label": "Field", + "read_only": 1 + }, + { + "fieldname": "specification", + "fieldtype": "Link", + "label": "Specification", + "options": "Specification", + "reqd": 1 + } + ], + "index_web_pages_for_search": 1, + "links": [], + "modified": "2024-06-08 11:46:12.702788", + "modified_by": "Administrator", + "module": "Inventory Tools", + "name": "Specification Value", + "owner": "Administrator", + "permissions": [ + { + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "System Manager", + "share": 1, + "write": 1 + } + ], + "sort_field": "modified", + "sort_order": "DESC", + "states": [], + "title_field": "value" +} diff --git a/inventory_tools/inventory_tools/doctype/specification_value/specification_value_list.js b/inventory_tools/inventory_tools/doctype/specification_value/specification_value_list.js index c168b01..7f8dd79 100644 --- a/inventory_tools/inventory_tools/doctype/specification_value/specification_value_list.js +++ b/inventory_tools/inventory_tools/doctype/specification_value/specification_value_list.js @@ -1,3 +1,6 @@ +// Copyright (c) 2024, AgriTheory and contributors +// For license information, please see license.txt + frappe.listview_settings['Specification Value'] = { refresh: listview => { console.log('this', listview) diff --git a/inventory_tools/inventory_tools/faceted_search.py b/inventory_tools/inventory_tools/faceted_search.py index 6a30704..d2f9284 100644 --- a/inventory_tools/inventory_tools/faceted_search.py +++ b/inventory_tools/inventory_tools/faceted_search.py @@ -1,10 +1,13 @@ +# Copyright (c) 2024, AgriTheory and contributors +# For license information, please see license.txt + import json from time import localtime import frappe -from erpnext.e_commerce.product_data_engine.filters import ProductFiltersBuilder -from erpnext.e_commerce.product_data_engine.query import ProductQuery -from erpnext.setup.doctype.item_group.item_group import get_child_groups_for_website +from webshop.webshop.product_data_engine.filters import ProductFiltersBuilder +from webshop.webshop.product_data_engine.query import ProductQuery +from webshop.webshop.doctype.override_doctype.item_group import get_child_groups_for_website from frappe.utils.data import cint, flt, getdate from inventory_tools.inventory_tools.doctype.specification.specification import convert_to_epoch diff --git a/inventory_tools/inventory_tools/overrides/stock_entry.py b/inventory_tools/inventory_tools/overrides/stock_entry.py index e2cb539..6852018 100644 --- a/inventory_tools/inventory_tools/overrides/stock_entry.py +++ b/inventory_tools/inventory_tools/overrides/stock_entry.py @@ -54,18 +54,18 @@ def check_if_operations_completed(self): def validate_finished_goods(self): """ -<<<<<<< HEAD - HASH: 153e0ba81b62acc170a951a289363fff5579edc7 -======= - HASH: 54791e938bd56eb81f7d8d923381a006998919fe ->>>>>>> 12d5afa2ce39627719b130a5ed0e5ce879c818f6 - REPO: https://github.com/frappe/erpnext/ - PATH: erpnext/stock/doctype/stock_entry/stock_entry.py - METHOD: validate_finished_goods - - 1. Check if FG exists (mfg, repack) - 2. Check if Multiple FG Items are present (mfg) - 3. Check FG Item and Qty against WO if present (mfg) + <<<<<<< HEAD + HASH: 153e0ba81b62acc170a951a289363fff5579edc7 + ======= + HASH: 54791e938bd56eb81f7d8d923381a006998919fe + >>>>>>> 12d5afa2ce39627719b130a5ed0e5ce879c818f6 + REPO: https://github.com/frappe/erpnext/ + PATH: erpnext/stock/doctype/stock_entry/stock_entry.py + METHOD: validate_finished_goods + + 1. Check if FG exists (mfg, repack) + 2. Check if Multiple FG Items are present (mfg) + 3. Check FG Item and Qty against WO if present (mfg) """ production_item, wo_qty, finished_items = None, 0, [] @@ -124,17 +124,17 @@ def validate_finished_goods(self): def get_pending_raw_materials(self, backflush_based_on=None): """ -<<<<<<< HEAD - HASH: 153e0ba81b62acc170a951a289363fff5579edc7 -======= - HASH: 54791e938bd56eb81f7d8d923381a006998919fe ->>>>>>> 12d5afa2ce39627719b130a5ed0e5ce879c818f6 - REPO: https://github.com/frappe/erpnext/ - PATH: erpnext/stock/doctype/stock_entry/stock_entry.py - METHOD: get_pending_raw_materials - - issue (item quantity) that is pending to issue or desire to transfer, - whichever is less + <<<<<<< HEAD + HASH: 153e0ba81b62acc170a951a289363fff5579edc7 + ======= + HASH: 54791e938bd56eb81f7d8d923381a006998919fe + >>>>>>> 12d5afa2ce39627719b130a5ed0e5ce879c818f6 + REPO: https://github.com/frappe/erpnext/ + PATH: erpnext/stock/doctype/stock_entry/stock_entry.py + METHOD: get_pending_raw_materials + + issue (item quantity) that is pending to issue or desire to transfer, + whichever is less """ item_dict = self.get_pro_order_required_items(backflush_based_on) diff --git a/inventory_tools/inventory_tools/report/specification/__init__.py b/inventory_tools/inventory_tools/report/specification/__init__.py index e69de29..6b9109e 100644 --- a/inventory_tools/inventory_tools/report/specification/__init__.py +++ b/inventory_tools/inventory_tools/report/specification/__init__.py @@ -0,0 +1,2 @@ +# Copyright (c) 2024, AgriTheory and contributors +# For license information, please see license.txt diff --git a/inventory_tools/inventory_tools/report/specification/specification.json b/inventory_tools/inventory_tools/report/specification/specification.json index 6706ccb..1319248 100644 --- a/inventory_tools/inventory_tools/report/specification/specification.json +++ b/inventory_tools/inventory_tools/report/specification/specification.json @@ -1,29 +1,29 @@ { - "add_total_row": 0, - "columns": [], - "creation": "2023-11-24 15:51:03.630333", - "disable_prepared_report": 0, - "disabled": 0, - "docstatus": 0, - "doctype": "Report", - "filters": [], - "idx": 0, - "is_standard": "Yes", - "modified": "2023-11-24 15:51:03.630333", - "modified_by": "Administrator", - "module": "Inventory Tools", - "name": "Specification", - "owner": "Administrator", - "prepared_report": 0, - "ref_doctype": "Specification", - "report_name": "Specification", - "report_type": "Script Report", - "roles": [ - { - "role": "System Manager" - }, - { - "role": "Item Manager" - } - ] -} \ No newline at end of file + "add_total_row": 0, + "columns": [], + "creation": "2023-11-24 15:51:03.630333", + "disable_prepared_report": 0, + "disabled": 0, + "docstatus": 0, + "doctype": "Report", + "filters": [], + "idx": 0, + "is_standard": "Yes", + "modified": "2023-11-24 15:51:03.630333", + "modified_by": "Administrator", + "module": "Inventory Tools", + "name": "Specification", + "owner": "Administrator", + "prepared_report": 0, + "ref_doctype": "Specification", + "report_name": "Specification", + "report_type": "Script Report", + "roles": [ + { + "role": "System Manager" + }, + { + "role": "Item Manager" + } + ] +} diff --git a/inventory_tools/patches/rename_alternative_workstation.py b/inventory_tools/patches/rename_alternative_workstation.py index 7ca7c6c..cbf43d5 100644 --- a/inventory_tools/patches/rename_alternative_workstation.py +++ b/inventory_tools/patches/rename_alternative_workstation.py @@ -1,11 +1,14 @@ -import frappe -from frappe.model.rename_doc import rename_doc - - -def execute(): - if frappe.db.exists("DocType", "Alternative Workstations"): - rename_doc( - "DocType", "Alternative Workstations", "Alternative Workstation", ignore_if_exists=True - ) - - frappe.reload_doc("inventory_tools", "doctype", "alternative_workstation", force=True) +# Copyright (c) 2024, AgriTheory and contributors +# For license information, please see license.txt + +import frappe +from frappe.model.rename_doc import rename_doc + + +def execute(): + if frappe.db.exists("DocType", "Alternative Workstations"): + rename_doc( + "DocType", "Alternative Workstations", "Alternative Workstation", ignore_if_exists=True + ) + + frappe.reload_doc("inventory_tools", "doctype", "alternative_workstation", force=True) diff --git a/inventory_tools/public/js/faceted_search/AttributeFilter.vue b/inventory_tools/public/js/faceted_search/AttributeFilter.vue index f474cb0..468b70f 100644 --- a/inventory_tools/public/js/faceted_search/AttributeFilter.vue +++ b/inventory_tools/public/js/faceted_search/AttributeFilter.vue @@ -19,9 +19,7 @@ export default { this.$emit('update_filters', { attribute_name: this.attribute_name, attribute_id: this.attribute_id, - values: this.selectedValues - .map(r => r.isChecked ? r.attribute : null) - .filter(r => r != null), + values: this.selectedValues.map(r => (r.isChecked ? r.attribute : null)).filter(r => r != null), }) }, }, diff --git a/inventory_tools/public/js/faceted_search/FacetedSearch.vue b/inventory_tools/public/js/faceted_search/FacetedSearch.vue index 885bf55..9773afa 100644 --- a/inventory_tools/public/js/faceted_search/FacetedSearch.vue +++ b/inventory_tools/public/js/faceted_search/FacetedSearch.vue @@ -33,8 +33,8 @@ export default { doctype: { type: String, required: true, - default: 'Item' - } + default: 'Item', + }, }, data() { return { searchComponents: [], filterValues: {}, sortOrder: '' } @@ -50,7 +50,7 @@ export default { if ('sort_order' in values) { this.sortOrder = values } else { - this.filterValues[values.attribute_name] = { attribute_id: values.attribute_id, values: values.values} + this.filterValues[values.attribute_name] = { attribute_id: values.attribute_id, values: values.values } } watchDebounced( @@ -59,46 +59,49 @@ export default { console.log('changed!') await this.setFilterValues() }, - { debounce: 500, maxWait: 1000 }, + { debounce: 500, maxWait: 1000 } ) }, loadFacets() { - frappe.call({ - method: 'inventory_tools.inventory_tools.faceted_search.show_faceted_search_components', - args: { 'doctype': this.doctype, 'filters': this.filterValues }, - headers: { 'X-Frappe-CSRF-Token': frappe.csrf_token }, - }, - ).then(r => { - this.searchComponents = r.message - for (const value of Object.values(r.message)) { - this.updateFilters(value) - } - }) + frappe + .call({ + method: 'inventory_tools.inventory_tools.faceted_search.show_faceted_search_components', + args: { doctype: this.doctype, filters: this.filterValues }, + headers: { 'X-Frappe-CSRF-Token': frappe.csrf_token }, + }) + .then(r => { + this.searchComponents = r.message + for (const value of Object.values(r.message)) { + this.updateFilters(value) + } + }) }, async setFilterValues() { if (erpnext.e_commerce) { - frappe.xcall('erpnext.e_commerce.api.get_product_filter_data', { - query_args: { attributes: this.filterValues, sort_order: this.sortOrder } - }).then(r => { - let view_type = localStorage.getItem("product_view") || "List View"; - if (!r.items) { - return - } else if (view_type == 'List View') { - new erpnext.ProductList({ - items: r.items, - products_section: $("#products-list-area"), - settings: r.settings, - preference: view_type - }) - } else { - new erpnext.ProductGrid({ - items: r.items, - products_section: $("#products-grid-area"), - settings: r.settings, - preference: view_type - }) - } - }) + frappe + .xcall('erpnext.e_commerce.api.get_product_filter_data', { + query_args: { attributes: this.filterValues, sort_order: this.sortOrder }, + }) + .then(r => { + let view_type = localStorage.getItem('product_view') || 'List View' + if (!r.items) { + return + } else if (view_type == 'List View') { + new erpnext.ProductList({ + items: r.items, + products_section: $('#products-list-area'), + settings: r.settings, + preference: view_type, + }) + } else { + new erpnext.ProductGrid({ + items: r.items, + products_section: $('#products-grid-area'), + settings: r.settings, + preference: view_type, + }) + } + }) } else { const items = await frappe.xcall('inventory_tools.inventory_tools.faceted_search.get_specification_items', { attributes: this.filterValues, @@ -160,7 +163,7 @@ export default { listview.filter_area.set(filters) listview.refresh() }, - } + }, } @@ -210,5 +213,5 @@ export default { .scrollable-filter:hover { scrollbar-color: var(--primary) #eee; } - } +} diff --git a/inventory_tools/public/js/faceted_search/FacetedSearchColorPicker.vue b/inventory_tools/public/js/faceted_search/FacetedSearchColorPicker.vue index 02c3ab7..9e8e123 100644 --- a/inventory_tools/public/js/faceted_search/FacetedSearchColorPicker.vue +++ b/inventory_tools/public/js/faceted_search/FacetedSearchColorPicker.vue @@ -1,110 +1,113 @@ - - - - \ No newline at end of file + + + + diff --git a/inventory_tools/public/js/faceted_search/FacetedSearchDateRange.vue b/inventory_tools/public/js/faceted_search/FacetedSearchDateRange.vue index 7d57cd9..adce776 100644 --- a/inventory_tools/public/js/faceted_search/FacetedSearchDateRange.vue +++ b/inventory_tools/public/js/faceted_search/FacetedSearchDateRange.vue @@ -1,69 +1,66 @@ - - - - + + + diff --git a/inventory_tools/public/js/faceted_search/FacetedSearchNumericRange.vue b/inventory_tools/public/js/faceted_search/FacetedSearchNumericRange.vue index 0b468b7..d1fa37c 100644 --- a/inventory_tools/public/js/faceted_search/FacetedSearchNumericRange.vue +++ b/inventory_tools/public/js/faceted_search/FacetedSearchNumericRange.vue @@ -1,72 +1,65 @@ - - - - + + + diff --git a/inventory_tools/public/js/faceted_search/api.js b/inventory_tools/public/js/faceted_search/api.js index c5834ec..68e794f 100644 --- a/inventory_tools/public/js/faceted_search/api.js +++ b/inventory_tools/public/js/faceted_search/api.js @@ -1,3 +1,6 @@ +// Copyright (c) 2024, AgriTheory and contributors +// For license information, please see license.txt + function getSearchComponents(doctype) { frappe.ready(() => { frappe.call({ diff --git a/inventory_tools/public/js/faceted_search/faceted_search.js b/inventory_tools/public/js/faceted_search/faceted_search.js index a9f69fc..237beef 100644 --- a/inventory_tools/public/js/faceted_search/faceted_search.js +++ b/inventory_tools/public/js/faceted_search/faceted_search.js @@ -1,3 +1,6 @@ +// Copyright (c) 2024, AgriTheory and contributors +// For license information, please see license.txt + import { createApp } from 'vue' import FacetedSearch from './FacetedSearch.vue' diff --git a/inventory_tools/public/js/faceted_search/specification_dialog.js b/inventory_tools/public/js/faceted_search/specification_dialog.js index 713e1fb..823458e 100644 --- a/inventory_tools/public/js/faceted_search/specification_dialog.js +++ b/inventory_tools/public/js/faceted_search/specification_dialog.js @@ -1,3 +1,6 @@ +// Copyright (c) 2024, AgriTheory and contributors +// For license information, please see license.txt + frappe.provide('inventory_tools') inventory_tools.specification_dialog = async frm => { diff --git a/inventory_tools/public/js/vite.config.js b/inventory_tools/public/js/vite.config.js index 2b10ce8..ad94684 100644 --- a/inventory_tools/public/js/vite.config.js +++ b/inventory_tools/public/js/vite.config.js @@ -1,15 +1,13 @@ +// Copyright (c) 2024, AgriTheory and contributors +// For license information, please see license.txt + import { defineConfig } from 'vite' import vue from '@vitejs/plugin-vue' import path from 'path' -import { getProxyOptions } from 'frappe-ui/src/utils/vite-dev-server' // https://vitejs.dev/config/ export default defineConfig({ plugins: [vue()], - server: { - port: 8080, - proxy: getProxyOptions({ port: 8003 }), - }, build: { lib: { entry: path.resolve(__dirname, './faceted_search/faceted_search.js'), @@ -17,8 +15,7 @@ export default defineConfig({ fileName: format => `inventory_tools.js`, // creates module only output }, outDir: './inventory_tools/public/dist/js', - root: './', - target: 'es2015', + target: 'esnext', emptyOutDir: false, minify: false, }, diff --git a/inventory_tools/tests/fixtures.py b/inventory_tools/tests/fixtures.py index 7d94e43..8d4f7da 100644 --- a/inventory_tools/tests/fixtures.py +++ b/inventory_tools/tests/fixtures.py @@ -1,1012 +1,1180 @@ -# Copyright (c) 2024, AgriTheory and contributors -# For license information, please see license.txt - -suppliers = [ - ( - "Freedom Provisions", - None, - None, - None, - "Net 30", - { - "address_line1": "16 Margrave", - "city": "Carlisle", - "state": "NH", - "country": "United States", - "pincode": "57173", - }, - ), - ( - "Unity Bakery Supply", - None, - None, - None, - "Net 30", - { - "address_line1": "34 Pinar St", - "city": "Unity", - "state": "RI", - "country": "United States", - "pincode": "34291", - }, - ), - ( - "Chelsea Fruit Co", - None, - None, - None, - "Net 30", - { - "address_line1": "67C Sweeny Street", - "city": "Chelsea", - "state": "MA", - "country": "United States", - "pincode": "89077", - }, - ), - ( - "Credible Contract Baking", - None, - None, - None, - "Net 30", - { - "address_line1": "4 Crumb Circle", - "city": "Belmont", - "state": "MA", - "country": "United States", - "pincode": "89074", - }, - ), - ( - "Southern Fruit Supply", - None, - None, - None, - "Net 30", - { - "address_line1": "10001 Pineapple Way", - "city": "Largo", - "state": "TX", - "country": "United States", - "pincode": "89574", - }, - ), -] - -workstations = [ - ("Mix Pie Crust Station", "20"), - ("Roll Pie Crust Station", "20"), - ("Make Pie Filling Station", "20"), - ("Cooling Station", "100"), - ("Box Pie Station", "100"), - ("Baking Station", "20"), - ("Assemble Pie Station", "20"), - ("Mix Pie Filling Station", "20"), - ("Packaging Station", "2"), - ("Food Prep Table 2", "10"), - ("Food Prep Table 1", "5"), - ("Range Station", "20"), - ("Cooling Racks Station", "80"), - ("Refrigerator Station", "200"), - ("Oven Station", "20"), - ("Mixer Station", "10"), -] - -operations = [ - ( - "Gather Pie Crust Ingredients", - "Food Prep Table 2", - "5", - """- Remove flour, salt, and a pie tins from store room - - Remove butter and ice water from refrigerator - - Place ingredients at workstation - - Measure amounts for batch size into mixing bowl""", - ["Food Prep Table 1"], - ), - ( - "Gather Pie Filling Ingredients", - "Food Prep Table 1", - "5", - """- Remove fruit and butter from refrigerator - - Remove sugar and cornstarch - - Get water from sink - - Measure ingredients and place in pot, excluding 1/4 of fruit and butter""", - ["Food Prep Table 2"], - ), - ( - "Assemble Pie Op", - "Food Prep Table 2", - "5", - """- Use fresh pie filling or remove from refrigerator - - Remove rolled pie crusts from refrigerator - - Fill bottom crust with filling - - Create decorative cut out for top crust - - Layer top crust over bottom crust / filling and create a crimped seal""", - ["Food Prep Table 1", "Assemble Pie Station"], - ), - ( - "Cook Pie Filling Operation", - "Range Station", - "5", - """- Bring ingredients to simmer and cook for 15 minutes - - Remove from heat and mix in remaining 1/4 berries and butter - - Store in refrigerator if not using immediately""", - ), - ( - "Mix Dough Op", - "Mixer Station", - "5", - """- Combine flour, butter, salt, and ice water in mixer - - Pulse for 30 seconds - - Divide into equal-sized portions, one portion for each pie crust being made - - Put in refrigerator""", - ["Mix Pie Crust Station", "Mix Pie Filling Station"], - ), - ("Box Pie Op", "Packaging Station", "5", "- Place pie into box for sale"), - ( - "Roll Pie Crust Op", - "Food Prep Table 2", - "5", - """- Remove chilled pie crust portions from refrigerator - - Separate each portion into two (one for bottom crust, one for top) - - Flour board and roll out each portion into a circle - - Place bottom crust into pie tin, then layer a piece of parchment paper, followed by the top crust""", - ["Food Prep Table 1", "Roll Pie Crust Station"], - ), - ("Divide Dough Op", "Food Prep Table 2", "1", "Divide Dough Op", ["Food Prep Table 1"]), - ( - "Bake Op", - "Oven Station", - "1", - """- Place assembled pies into oven - - Bake at 375F for 50 minutes - - Remove from oven""", - ["Baking Station"], - ), - ( - "Chill Pie Crust Op", - "Refrigerator Station", - "1", - "- Chill pie crust for at least 30 minutes", - ["Cooling Station", "Cooling Racks Station"], - ), - ( - "Cool Pie Op", - "Cooling Racks Station", - "1", - "Cool baked pies for at least 30 minutes before boxing", - ["Cooling Station", "Refrigerator Station"], - ), - ( - "Assemble Pocket Op", - "Food Prep Table 1", - "5", - """- Fold 3 poppers into dough pocket""", - ), - ( - "Assemble Popper Op", - "Food Prep Table 1", - "5", - """- Top dough bite with fruit""", - ), - ( - "Assemble Combination Product", - "Food Prep Table 1", - "5", - """- Tower: package one pie and one pocket, and one popper - - Pocketful of Bay: package one pocket with two poppers""", - ), -] - -items = [ - { - "item_code": "Ambrosia Pie", - "item_group": "Baked Goods", - "uom": "Nos", - "item_price": 11.00, - "default_warehouse": "Refrigerated Display - APC", - "description": "

Ambrosia Pie is the marquee product of Ambrosia Pie Company. A filling of heavenly cloudberries pair perfectly with the tart hairless rambutan, finished with drizzles of tayberry nectar. It's a feast fit for Mt Olympus!

", - }, - { - "item_code": "Double Plum Pie", - "uom": "Nos", - "item_group": "Baked Goods", - "item_price": 10.50, - "default_warehouse": "Refrigerated Display - APC", - "description": "

Double the fun and double the flavor with our Double Plum Pie! We combine damson and cocoplums in a daring tropical-meets-temperate filling. Forbidden fruit never tasted this good.

", - }, - { - "item_code": "Gooseberry Pie", - "uom": "Nos", - "item_group": "Baked Goods", - "item_price": 12.00, - "default_warehouse": "Refrigerated Display - APC", - "description": "

Our delicious take on the traditional gooseberry pie that tastes like the holidays. This classic pie is best shared with the ones you love.

", - }, - { - "item_code": "Kaduka Key Lime Pie", - "item_group": "Baked Goods", - "uom": "Nos", - "item_price": 11.50, - "default_warehouse": "Refrigerated Display - APC", - "description": "

Take your tastebuds on an adventure with this whimsical twist on the classic Key Lime pie. Made with kaduka limes and the exotic limequat, this seasonal pie is sure to satisfy even the most weary culinary explorer. Grab it when you can - it's only available April through September.

", - }, - { - "item_code": "Tower of Bay-bel", - "uom": "Nos", - "item_group": "Baked Goods", - "item_price": 20.00, - "default_warehouse": "Refrigerated Display - APC", - "description": "

Reach for the stars with this epic all-things-bayberry dessert that stacks a Bayberry Pocket on top of our Bayberry Pie.

", - }, - { - "item_code": "Pocketful of Bay", - "uom": "Nos", - "item_group": "Baked Goods", - "item_price": 12.00, - "default_warehouse": "Refrigerated Display - APC", - "description": "

Try this delightful combination of a Bayberry Pocket and two additional Bayberry Poppers.

", - }, - { - "item_code": "Bayberry Pie", - "uom": "Nos", - "item_group": "Sub Assemblies", - # "item_price": 11.00, # can a finished good be included as sub-assembly for another good? - "default_warehouse": "Refrigerated Display - APC", - "description": "

This pie features the sweet and scrumptious bayberry and is sure to be a crowd-pleaser.

", - }, - { - "item_code": "Bayberry Pocket", - "uom": "Nos", - "item_group": "Sub Assemblies", - # "item_price": 8.00, - "default_warehouse": "Refrigerated Display - APC", - "description": "

Need a little more than one popper? The Bayberry Pocket is a tasty dough pocket stuffed with several Bayberry Poppers.

", - }, - { - "item_code": "Bayberry Popper", - "uom": "Nos", - "item_group": "Sub Assemblies", - # "item_price": 3.00, - "default_warehouse": "Refrigerated Display - APC", - "description": "

Part cookie, part tart, these bite-sized treats will bring a little sweetness to your day.

", - }, - { - "item_code": "Ambrosia Pie Filling", - "uom": "Cup", - "item_group": "Sub Assemblies", - "default_warehouse": "Refrigerator - APC", - "description": "Ambrosia Pie Filling", - }, - { - "item_code": "Double Plum Pie Filling", - "uom": "Cup", - "item_group": "Sub Assemblies", - "default_warehouse": "Refrigerator - APC", - "description": "Double Plum Pie Filling", - }, - { - "item_code": "Gooseberry Pie Filling", - "uom": "Cup", - "description": "Gooseberry Pie Filling", - "item_group": "Sub Assemblies", - "default_warehouse": "Refrigerator - APC", - }, - { - "item_code": "Bayberry Pie Filling", - "uom": "Cup", - "description": "Bayberry Pie Filling", - "item_group": "Sub Assemblies", - "default_warehouse": "Refrigerator - APC", - }, - { - "item_code": "Kaduka Key Lime Pie Filling", - "item_group": "Sub Assemblies", - "default_warehouse": "Refrigerator - APC", - "uom": "Cup", - "description": "Kaduka Key Lime Pie Filling", - }, - { - "item_code": "Pie Crust", - "uom": "Nos", - "description": "Pie Crust", - "item_group": "Sub Assemblies", - "default_warehouse": "Refrigerator - APC", - "is_sub_contracted_item": 1, - "item_price": 2.00, - "default_supplier": "", - "supplier": "", - "valuation_rate": 3.0196, - "uom_conversion_detail": {"Hour": 20}, - }, - { - "item_code": "Pie Crust Service per Crust", - "uom": "Nos", - "description": "Subcontracted pie crust manufacturing service. Item price is per crust.", - "item_group": "Sub Assemblies", - "default_warehouse": "Credible Contract Baking - APC", - "is_sub_contracted_item": 1, - "is_stock_item": 0, - "item_price": 2.00, - "default_supplier": "Credible Contract Baking", - "supplier": "Credible Contract Baking", - }, - { - "item_code": "Pie Crust Service per Hour", - "uom": "Hour", - "description": "Subcontracted pie crust manufacturing service. Item price is per hour.", - "item_group": "Sub Assemblies", - "default_warehouse": "Credible Contract Baking - APC", - "is_sub_contracted_item": 1, - "is_stock_item": 0, - "item_price": 40.00, # Assumes 5 crusts takes 15 mins (excluding chilling time), or 20 crusts/hour at rate of $2.00/crust - "default_supplier": "Credible Contract Baking", - "supplier": "Credible Contract Baking", - }, - { - "item_code": "Cloudberry", - "uom": "Pound", - "description": "Cloudberry", - "item_group": "Ingredients", - "item_price": 0.65, - "default_warehouse": "Refrigerator - APC", - "supplier": ["Chelsea Fruit Co", "Southern Fruit Supply"], - }, - { - "item_code": "Cocoplum", - "uom": "Pound", - "description": "Cocoplum", - "item_group": "Ingredients", - "item_price": 0.35, - "default_warehouse": "Refrigerator - APC", - "supplier": ["Chelsea Fruit Co", "Southern Fruit Supply"], - }, - { - "item_code": "Damson Plum", - "uom": "Pound", - "description": "Damson Plum", - "item_group": "Ingredients", - "item_price": 0.85, - "default_warehouse": "Refrigerator - APC", - "supplier": ["Chelsea Fruit Co", "Southern Fruit Supply"], - }, - { - "item_code": "Gooseberry", - "uom": "Pound", - "description": "Gooseberry", - "item_group": "Ingredients", - "item_price": 0.99, - "default_warehouse": "Refrigerator - APC", - "supplier": ["Chelsea Fruit Co", "Southern Fruit Supply"], - }, - { - "item_code": "Hairless Rambutan", - "uom": "Pound", - "description": "Hairless Rambutan", - "item_price": 0.50, - "item_group": "Ingredients", - "default_warehouse": "Storeroom - APC", - "supplier": ["Chelsea Fruit Co", "Southern Fruit Supply"], - }, - { - "item_code": "Kaduka Lime", - "uom": "Pound", - "description": "Kaduka Lime", - "item_group": "Ingredients", - "item_price": 0.89, - "default_warehouse": "Refrigerator - APC", - "supplier": ["Chelsea Fruit Co", "Southern Fruit Supply"], - }, - { - "item_code": "Limequat", - "uom": "Pound", - "description": "Limequat", - "item_group": "Ingredients", - "item_price": 0.75, - "default_warehouse": "Refrigerator - APC", - "supplier": ["Chelsea Fruit Co", "Southern Fruit Supply"], - }, - { - "item_code": "Tayberry", - "uom": "Pound", - "description": "Tayberry", - "item_group": "Ingredients", - "item_price": 0.85, - "default_warehouse": "Refrigerator - APC", - "supplier": ["Chelsea Fruit Co", "Southern Fruit Supply"], - }, - { - "item_code": "Bayberry", - "uom": "Pound", - "description": "Bayberry", - "item_group": "Ingredients", - "item_price": 0.45, - "default_warehouse": "Refrigerator - APC", - "supplier": ["Chelsea Fruit Co", "Southern Fruit Supply"], - }, - { - "item_code": "Butter", - "uom": "Pound", - "description": "Butter", - "item_group": "Ingredients", - "item_price": 4.5, - "default_warehouse": "Refrigerator - APC", - "supplier": [ - "Freedom Provisions", - "Chelsea Fruit Co", - ], - }, - { - "item_code": "Cornstarch", - "uom": "Pound", - "description": "Cornstarch", - "item_group": "Ingredients", - "item_price": 0.52, - "default_warehouse": "Storeroom - APC", - "supplier": "Freedom Provisions", - }, - { - "item_code": "Ice Water", - "uom": "Cup", - "description": "Ice Water - necessary for pie crusts", - "item_group": "Ingredients", - "item_price": 0.01, - "default_warehouse": "Refrigerator - APC", - "available_in_house": 1, - "opening_qty": 50, - }, - { - "item_code": "Flour", - "uom": "Pound", - "description": "Flour", - "item_group": "Ingredients", - "item_price": 0.66, - "default_warehouse": "Storeroom - APC", - "supplier": "Freedom Provisions", - }, - { - "item_code": "Pie Box", - "uom": "Nos", - "description": "Pie Box", - "item_group": "Bakery Supplies", - "item_price": 0.4, - "default_warehouse": "Storeroom - APC", - "supplier": ["Freedom Provisions", "Unity Bakery Supply"], - }, - { - "item_code": "Pie Tin", - "uom": "Nos", - "description": "Pie Tin", - "item_price": 0.18, - "item_group": "Bakery Supplies", - "default_warehouse": "Storeroom - APC", - "supplier": ["Freedom Provisions", "Unity Bakery Supply"], - }, - { - "item_code": "Parchment Paper", - "uom": "Nos", - "description": "Parchment Paper", - "item_group": "Bakery Supplies", - "item_price": 0.02, - "default_warehouse": "Storeroom - APC", - "supplier": ["Freedom Provisions", "Unity Bakery Supply"], - "uom_conversion_detail": {"Box": 100}, - }, - { - "item_code": "Salt", - "uom": "Pound", - "description": "Salt", - "item_group": "Ingredients", - "item_price": 0.36, - "default_warehouse": "Storeroom - APC", - "supplier": "Freedom Provisions", - }, - { - "item_code": "Sugar", - "uom": "Pound", - "description": "Sugar", - "item_group": "Ingredients", - "item_price": 0.60, - "default_warehouse": "Storeroom - APC", - "supplier": "Freedom Provisions", - }, - { - "item_code": "Water", - "uom": "Cup", - "item_price": 0.05, - "description": "Water", - "item_group": "Ingredients", - "default_warehouse": "Kitchen - APC", - "available_in_house": 1, - "opening_qty": 50, - }, -] - -boms = [ - { - "item": "Tower of Bay-bel", - "quantity": 5.0, - "uom": "Nos", - "items": [ - {"item_code": "Bayberry Pie", "qty": 5.0, "qty_consumed_per_unit": 1.0, "uom": "Nos"}, - {"item_code": "Bayberry Pocket", "qty": 5.0, "qty_consumed_per_unit": 1.0, "uom": "Nos"}, - ], - "operations": [ - { - "batch_size": 5, - "operation": "Assemble Combination Product", - "time_in_mins": 2.0, - "workstation": "Food Prep Table 1", - }, - ], - }, - { - "item": "Pocketful of Bay", - "quantity": 5.0, - "uom": "Nos", - "items": [ - {"item_code": "Bayberry Pocket", "qty": 5.0, "qty_consumed_per_unit": 1.0, "uom": "Nos"}, - {"item_code": "Bayberry Popper", "qty": 10.0, "qty_consumed_per_unit": 2.0, "uom": "Nos"}, - {"item_code": "Pie Box", "qty": 5.0, "qty_consumed_per_unit": 1.0, "uom": "Nos"}, - ], - "operations": [ - { - "batch_size": 5, - "operation": "Assemble Combination Product", - "time_in_mins": 2.0, - "workstation": "Food Prep Table 1", - }, - ], - }, - { - "item": "Bayberry Pocket", - "quantity": 5.0, - "uom": "Nos", - "items": [ - {"item_code": "Flour", "qty": 1.5, "qty_consumed_per_unit": 0.3, "uom": "Pound"}, - {"item_code": "Butter", "qty": 0.75, "qty_consumed_per_unit": 0.15, "uom": "Pound"}, - {"item_code": "Sugar", "qty": 0.1, "qty_consumed_per_unit": 0.02, "uom": "Pound"}, - {"item_code": "Bayberry Popper", "qty": 15.0, "qty_consumed_per_unit": 3.0, "uom": "Nos"}, - ], - "operations": [ - { - "batch_size": 5, - "operation": "Mix Dough Op", - "time_in_mins": 5.0, - "workstation": "Mixer Station", - }, - { - "batch_size": 5, - "operation": "Assemble Pocket Op", - "time_in_mins": 2.0, - "workstation": "Food Prep Table 1", - }, - ], - }, - { - "item": "Bayberry Popper", - "quantity": 5.0, - "uom": "Nos", - "items": [ - {"item_code": "Flour", "qty": 0.5, "qty_consumed_per_unit": 0.1, "uom": "Pound"}, - {"item_code": "Butter", "qty": 0.25, "qty_consumed_per_unit": 0.05, "uom": "Pound"}, - {"item_code": "Sugar", "qty": 0.05, "qty_consumed_per_unit": 0.01, "uom": "Pound"}, - {"item_code": "Bayberry", "qty": 1.0, "qty_consumed_per_unit": 0.2, "uom": "Pound"}, - ], - "operations": [ - { - "batch_size": 5, - "operation": "Mix Dough Op", - "time_in_mins": 5.0, - "workstation": "Mixer Station", - }, - { - "batch_size": 5, - "operation": "Assemble Popper Op", - "time_in_mins": 1.0, - "workstation": "Food Prep Table 1", - }, - ], - }, - { - "item": "Bayberry Pie", - "quantity": 5.0, - "uom": "Nos", - "items": [ - {"item_code": "Pie Crust", "qty": 5.0, "qty_consumed_per_unit": 1.0, "uom": "Nos"}, - { - "item_code": "Bayberry Pie Filling", - "qty": 20.0, - "qty_consumed_per_unit": 4.0, - "uom": "Cup", - }, - {"item_code": "Pie Box", "qty": 5.0, "qty_consumed_per_unit": 1.0, "uom": "Nos"}, - ], - "operations": [ - { - "batch_size": 5, - "operation": "Assemble Pie Op", - "time_in_mins": 10.0, - "workstation": "Food Prep Table 2", - }, - {"batch_size": 1, "operation": "Bake Op", "time_in_mins": 50.0, "workstation": "Oven Station"}, - { - "batch_size": 1, - "operation": "Cool Pie Op", - "time_in_mins": 30.0, - "workstation": "Cooling Racks Station", - }, - { - "batch_size": 5, - "operation": "Box Pie Op", - "time_in_mins": 5.0, - "workstation": "Packaging Station", - }, - ], - }, - { - "item": "Double Plum Pie", - "quantity": 5.0, - "uom": "Nos", - "items": [ - {"item_code": "Pie Crust", "qty": 5.0, "qty_consumed_per_unit": 1.0, "uom": "Nos"}, - { - "item_code": "Double Plum Pie Filling", - "qty": 20.0, - "qty_consumed_per_unit": 4.0, - "uom": "Cup", - }, - {"item_code": "Pie Box", "qty": 5.0, "qty_consumed_per_unit": 1.0, "uom": "Nos"}, - ], - "operations": [ - { - "batch_size": 5, - "operation": "Assemble Pie Op", - "time_in_mins": 10.0, - "workstation": "Food Prep Table 2", - }, - {"batch_size": 1, "operation": "Bake Op", "time_in_mins": 50.0, "workstation": "Oven Station"}, - { - "batch_size": 1, - "operation": "Cool Pie Op", - "time_in_mins": 30.0, - "workstation": "Cooling Racks Station", - }, - { - "batch_size": 5, - "operation": "Box Pie Op", - "time_in_mins": 5.0, - "workstation": "Packaging Station", - }, - ], - }, - { - "item": "Kaduka Key Lime Pie", - "quantity": 5.0, - "uom": "Nos", - "items": [ - {"item_code": "Pie Crust", "qty": 5.0, "qty_consumed_per_unit": 1.0, "uom": "Nos"}, - { - "item_code": "Kaduka Key Lime Pie Filling", - "qty": 20.0, - "qty_consumed_per_unit": 4.0, - "uom": "Cup", - }, - {"item_code": "Pie Box", "qty": 5.0, "qty_consumed_per_unit": 1.0, "uom": "Nos"}, - ], - "operations": [ - { - "batch_size": 5, - "operation": "Assemble Pie Op", - "time_in_mins": 10.0, - "workstation": "Food Prep Table 2", - }, - {"batch_size": 1, "operation": "Bake Op", "time_in_mins": 50.0, "workstation": "Oven Station"}, - { - "batch_size": 1, - "operation": "Cool Pie Op", - "time_in_mins": 30.0, - "workstation": "Cooling Racks Station", - }, - { - "batch_size": 5, - "operation": "Box Pie Op", - "time_in_mins": 5.0, - "workstation": "Packaging Station", - }, - ], - }, - { - "item": "Gooseberry Pie", - "quantity": 5.0, - "uom": "Nos", - "items": [ - {"item_code": "Pie Crust", "qty": 5.0, "qty_consumed_per_unit": 1.0, "uom": "Nos"}, - { - "item_code": "Gooseberry Pie Filling", - "qty": 20.0, - "qty_consumed_per_unit": 4.0, - "uom": "Cup", - }, - {"item_code": "Pie Box", "qty": 5.0, "qty_consumed_per_unit": 1.0, "uom": "Nos"}, - ], - "operations": [ - { - "batch_size": 5, - "operation": "Assemble Pie Op", - "time_in_mins": 10.0, - "workstation": "Food Prep Table 2", - }, - {"batch_size": 1, "operation": "Bake Op", "time_in_mins": 50.0, "workstation": "Oven Station"}, - { - "batch_size": 1, - "operation": "Cool Pie Op", - "time_in_mins": 30.0, - "workstation": "Cooling Racks Station", - }, - { - "batch_size": 5, - "operation": "Box Pie Op", - "time_in_mins": 5.0, - "workstation": "Packaging Station", - }, - ], - }, - { - "item": "Ambrosia Pie", - "quantity": 5.0, - "uom": "Nos", - "overproduction_percentage_for_work_order": 100, - "items": [ - {"item_code": "Pie Crust", "qty": 5.0, "qty_consumed_per_unit": 1.0, "uom": "Nos"}, - {"item_code": "Ambrosia Pie Filling", "qty": 20.0, "qty_consumed_per_unit": 4.0, "uom": "Cup"}, - {"item_code": "Pie Box", "qty": 5.0, "qty_consumed_per_unit": 1.0, "uom": "Nos"}, - ], - "operations": [ - { - "batch_size": 5, - "operation": "Assemble Pie Op", - "time_in_mins": 10.0, - "workstation": "Food Prep Table 2", - }, - {"batch_size": 1, "operation": "Bake Op", "time_in_mins": 50.0, "workstation": "Oven Station"}, - { - "batch_size": 1, - "operation": "Cool Pie Op", - "time_in_mins": 30.0, - "workstation": "Cooling Racks Station", - }, - { - "batch_size": 5, - "operation": "Box Pie Op", - "time_in_mins": 5.0, - "workstation": "Packaging Station", - }, - ], - }, - { - "item": "Bayberry Pie Filling", - "quantity": 20.0, - "uom": "Cup", - "items": [ - {"item_code": "Sugar", "qty": 0.5, "qty_consumed_per_unit": 0.025, "uom": "Pound"}, - {"item_code": "Cornstarch", "qty": 0.1, "qty_consumed_per_unit": 0.005, "uom": "Pound"}, - {"item_code": "Water", "qty": 1.25, "qty_consumed_per_unit": 0.0625, "uom": "Cup"}, - {"item_code": "Butter", "qty": 0.313, "qty_consumed_per_unit": 0.01565, "uom": "Pound"}, - {"item_code": "Bayberry", "qty": 15.0, "qty_consumed_per_unit": 0.05025, "uom": "Pound"}, - ], - "operations": [ - { - "batch_size": 5, - "operation": "Gather Pie Filling Ingredients", - "time_in_mins": 5.0, - "workstation": "Food Prep Table 1", - }, - { - "batch_size": 5, - "operation": "Cook Pie Filling Operation", - "time_in_mins": 15.0, - "workstation": "Range Station", - }, - ], - }, - { - "item": "Double Plum Pie Filling", - "quantity": 20.0, - "uom": "Cup", - "items": [ - {"item_code": "Sugar", "qty": 0.5, "qty_consumed_per_unit": 0.025, "uom": "Pound"}, - {"item_code": "Cornstarch", "qty": 0.1, "qty_consumed_per_unit": 0.005, "uom": "Pound"}, - {"item_code": "Water", "qty": 1.25, "qty_consumed_per_unit": 0.0625, "uom": "Cup"}, - {"item_code": "Butter", "qty": 0.313, "qty_consumed_per_unit": 0.01565, "uom": "Pound"}, - {"item_code": "Cocoplum", "qty": 7.5, "qty_consumed_per_unit": 0.02515, "uom": "Pound"}, - {"item_code": "Damson Plum", "qty": 7.5, "qty_consumed_per_unit": 0.02515, "uom": "Pound"}, - ], - "operations": [ - { - "batch_size": 5, - "operation": "Gather Pie Filling Ingredients", - "time_in_mins": 5.0, - "workstation": "Food Prep Table 1", - }, - { - "batch_size": 5, - "operation": "Cook Pie Filling Operation", - "time_in_mins": 15.0, - "workstation": "Range Station", - }, - ], - }, - { - "item": "Kaduka Key Lime Pie Filling", - "quantity": 20.0, - "uom": "Cup", - "items": [ - {"item_code": "Sugar", "qty": 0.5, "qty_consumed_per_unit": 0.025, "uom": "Pound"}, - {"item_code": "Cornstarch", "qty": 0.1, "qty_consumed_per_unit": 0.005, "uom": "Pound"}, - {"item_code": "Water", "qty": 1.25, "qty_consumed_per_unit": 0.0625, "uom": "Cup"}, - {"item_code": "Butter", "qty": 0.313, "qty_consumed_per_unit": 0.01565, "uom": "Pound"}, - {"item_code": "Kaduka Lime", "qty": 10.0, "qty_consumed_per_unit": 0.0335, "uom": "Pound"}, - {"item_code": "Limequat", "qty": 5.0, "qty_consumed_per_unit": 0.01675, "uom": "Pound"}, - ], - "operations": [ - { - "batch_size": 5, - "operation": "Gather Pie Filling Ingredients", - "time_in_mins": 5.0, - "workstation": "Food Prep Table 1", - }, - { - "batch_size": 5, - "operation": "Cook Pie Filling Operation", - "time_in_mins": 15.0, - "workstation": "Range Station", - }, - ], - }, - { - "item": "Gooseberry Pie Filling", - "quantity": 20.0, - "uom": "Cup", - "items": [ - {"item_code": "Sugar", "qty": 0.5, "qty_consumed_per_unit": 0.025, "uom": "Pound"}, - {"item_code": "Cornstarch", "qty": 0.1, "qty_consumed_per_unit": 0.005, "uom": "Pound"}, - {"item_code": "Water", "qty": 1.25, "qty_consumed_per_unit": 0.0625, "uom": "Cup"}, - {"item_code": "Butter", "qty": 0.313, "qty_consumed_per_unit": 0.01565, "uom": "Pound"}, - {"item_code": "Gooseberry", "qty": 15.0, "qty_consumed_per_unit": 0.05025, "uom": "Pound"}, - ], - "operations": [ - { - "batch_size": 5, - "operation": "Gather Pie Filling Ingredients", - "time_in_mins": 5.0, - "workstation": "Food Prep Table 1", - }, - { - "batch_size": 5, - "operation": "Cook Pie Filling Operation", - "time_in_mins": 15.0, - "workstation": "Range Station", - }, - ], - }, - { - "item": "Ambrosia Pie Filling", - "quantity": 20.0, - "uom": "Cup", - "items": [ - {"item_code": "Sugar", "qty": 0.5, "qty_consumed_per_unit": 0.025, "uom": "Pound"}, - {"item_code": "Cornstarch", "qty": 0.1, "qty_consumed_per_unit": 0.005, "uom": "Pound"}, - {"item_code": "Butter", "qty": 0.313, "qty_consumed_per_unit": 0.01565, "uom": "Pound"}, - { - "item_code": "Hairless Rambutan", - "qty": 5.0, - "qty_consumed_per_unit": 0.01675, - "uom": "Pound", - }, - {"item_code": "Tayberry", "qty": 2.5, "qty_consumed_per_unit": 0.0084, "uom": "Pound"}, - {"item_code": "Cloudberry", "qty": 7.5, "qty_consumed_per_unit": 0.02515, "uom": "Pound"}, - {"item_code": "Water", "qty": 1.25, "qty_consumed_per_unit": 0.0625, "uom": "Cup"}, - ], - "operations": [ - { - "batch_size": 5, - "operation": "Gather Pie Filling Ingredients", - "time_in_mins": 5.0, - "workstation": "Food Prep Table 1", - }, - { - "batch_size": 5, - "operation": "Cook Pie Filling Operation", - "time_in_mins": 15.0, - "workstation": "Range Station", - }, - ], - }, - { - "item": "Pie Crust", # Subcontracted BOM - "quantity": 5.0, - "uom": "Nos", - "is_default": 0, - "is_subcontracted": 1, - "with_operations": 0, - "items": [ - {"item_code": "Flour", "qty": 4.25, "qty_consumed_per_unit": 0.85, "uom": "Pound"}, - {"item_code": "Butter", "qty": 2.5, "qty_consumed_per_unit": 0.5, "uom": "Pound"}, - # {"item_code": "Ice Water", "qty": 2.5, "qty_consumed_per_unit": 0.5, "uom": "Cup"}, - {"item_code": "Salt", "qty": 0.05, "qty_consumed_per_unit": 0.01, "uom": "Pound"}, - {"item_code": "Parchment Paper", "qty": 5.0, "qty_consumed_per_unit": 1.0, "uom": "Nos"}, - {"item_code": "Pie Tin", "qty": 5.0, "qty_consumed_per_unit": 1.0, "uom": "Nos"}, - ], - "operations": [], # Subcontracted item -> operations done by supplier - }, - { - "item": "Pie Crust", # In-house BOM - "quantity": 5.0, - "uom": "Nos", - "items": [ - {"item_code": "Flour", "qty": 4.25, "qty_consumed_per_unit": 0.85, "uom": "Pound"}, - {"item_code": "Butter", "qty": 2.5, "qty_consumed_per_unit": 0.5, "uom": "Pound"}, - {"item_code": "Ice Water", "qty": 2.5, "qty_consumed_per_unit": 0.5, "uom": "Cup"}, - {"item_code": "Salt", "qty": 0.05, "qty_consumed_per_unit": 0.01, "uom": "Pound"}, - {"item_code": "Parchment Paper", "qty": 5.0, "qty_consumed_per_unit": 1.0, "uom": "Nos"}, - {"item_code": "Pie Tin", "qty": 5.0, "qty_consumed_per_unit": 1.0, "uom": "Nos"}, - ], - "operations": [ - { - "batch_size": 5, - "operation": "Gather Pie Crust Ingredients", - "time_in_mins": 5.0, - "workstation": "Food Prep Table 2", - }, - { - "batch_size": 5, - "operation": "Mix Dough Op", - "time_in_mins": 5.0, - "workstation": "Mixer Station", - }, - { - "batch_size": 1, - "operation": "Divide Dough Op", - "time_in_mins": 2.0, - "workstation": "Food Prep Table 2", - }, - { - "batch_size": 1, - "operation": "Chill Pie Crust Op", - "time_in_mins": 30.0, - "workstation": "Refrigerator Station", - }, - { - "batch_size": 5, - "operation": "Roll Pie Crust Op", - "time_in_mins": 10.0, - "workstation": "Food Prep Table 2", - }, - ], - }, -] - -customers = [ - "Almacs Food Group", - "Beans and Dreams Roasters", - "Cafe 27 Cafeteria", - "Capital Grille Restaurant Group", - "Downtown Deli", - "Draws Groceries", - "Grab n Go Bodega", - "Grand North Station Baking Co", - "Happy Basket Food Distribution Group", - "Jitter Cafe", - "Longwoods Sandwich Shop", - "Midtown Munchies Inc", - "My Way Cup Coffee", - "Nom Nom Cafe", - "Round the World Donut Shop", - "Sand Street Deli", - "Starfood Cafe", - "Terrywood Terminal Bakery Inc", - "TransAmerica Bank Cafeteria", - "Whole Harvest Grocery Group", -] +# Copyright (c) 2024, AgriTheory and contributors +# For license information, please see license.txt + +suppliers = [ + ( + "Freedom Provisions", + None, + None, + None, + "Net 30", + { + "address_line1": "16 Margrave", + "city": "Carlisle", + "state": "NH", + "country": "United States", + "pincode": "57173", + }, + ), + ( + "Unity Bakery Supply", + None, + None, + None, + "Net 30", + { + "address_line1": "34 Pinar St", + "city": "Unity", + "state": "RI", + "country": "United States", + "pincode": "34291", + }, + ), + ( + "Chelsea Fruit Co", + None, + None, + None, + "Net 30", + { + "address_line1": "67C Sweeny Street", + "city": "Chelsea", + "state": "MA", + "country": "United States", + "pincode": "89077", + }, + ), + ( + "Credible Contract Baking", + None, + None, + None, + "Net 30", + { + "address_line1": "4 Crumb Circle", + "city": "Belmont", + "state": "MA", + "country": "United States", + "pincode": "89074", + }, + ), + ( + "Southern Fruit Supply", + None, + None, + None, + "Net 30", + { + "address_line1": "10001 Pineapple Way", + "city": "Largo", + "state": "TX", + "country": "United States", + "pincode": "89574", + }, + ), +] + +workstations = [ + ("Mix Pie Crust Station", "20"), + ("Roll Pie Crust Station", "20"), + ("Make Pie Filling Station", "20"), + ("Cooling Station", "100"), + ("Box Pie Station", "100"), + ("Baking Station", "20"), + ("Assemble Pie Station", "20"), + ("Mix Pie Filling Station", "20"), + ("Packaging Station", "2"), + ("Food Prep Table 2", "10"), + ("Food Prep Table 1", "5"), + ("Range Station", "20"), + ("Cooling Racks Station", "80"), + ("Refrigerator Station", "200"), + ("Oven Station", "20"), + ("Mixer Station", "10"), +] + +operations = [ + ( + "Gather Pie Crust Ingredients", + "Food Prep Table 2", + "5", + """- Remove flour, salt, and a pie tins from store room + - Remove butter and ice water from refrigerator + - Place ingredients at workstation + - Measure amounts for batch size into mixing bowl""", + ["Food Prep Table 1"], + ), + ( + "Gather Pie Filling Ingredients", + "Food Prep Table 1", + "5", + """- Remove fruit and butter from refrigerator + - Remove sugar and cornstarch + - Get water from sink + - Measure ingredients and place in pot, excluding 1/4 of fruit and butter""", + ["Food Prep Table 2"], + ), + ( + "Assemble Pie Op", + "Food Prep Table 2", + "5", + """- Use fresh pie filling or remove from refrigerator + - Remove rolled pie crusts from refrigerator + - Fill bottom crust with filling + - Create decorative cut out for top crust + - Layer top crust over bottom crust / filling and create a crimped seal""", + ["Food Prep Table 1", "Assemble Pie Station"], + ), + ( + "Cook Pie Filling Operation", + "Range Station", + "5", + """- Bring ingredients to simmer and cook for 15 minutes + - Remove from heat and mix in remaining 1/4 berries and butter + - Store in refrigerator if not using immediately""", + ), + ( + "Mix Dough Op", + "Mixer Station", + "5", + """- Combine flour, butter, salt, and ice water in mixer + - Pulse for 30 seconds + - Divide into equal-sized portions, one portion for each pie crust being made + - Put in refrigerator""", + ["Mix Pie Crust Station", "Mix Pie Filling Station"], + ), + ("Box Pie Op", "Packaging Station", "5", "- Place pie into box for sale"), + ( + "Roll Pie Crust Op", + "Food Prep Table 2", + "5", + """- Remove chilled pie crust portions from refrigerator + - Separate each portion into two (one for bottom crust, one for top) + - Flour board and roll out each portion into a circle + - Place bottom crust into pie tin, then layer a piece of parchment paper, followed by the top crust""", + ["Food Prep Table 1", "Roll Pie Crust Station"], + ), + ("Divide Dough Op", "Food Prep Table 2", "1", "Divide Dough Op", ["Food Prep Table 1"]), + ( + "Bake Op", + "Oven Station", + "1", + """- Place assembled pies into oven + - Bake at 375F for 50 minutes + - Remove from oven""", + ["Baking Station"], + ), + ( + "Chill Pie Crust Op", + "Refrigerator Station", + "1", + "- Chill pie crust for at least 30 minutes", + ["Cooling Station", "Cooling Racks Station"], + ), + ( + "Cool Pie Op", + "Cooling Racks Station", + "1", + "Cool baked pies for at least 30 minutes before boxing", + ["Cooling Station", "Refrigerator Station"], + ), + ( + "Assemble Pocket Op", + "Food Prep Table 1", + "5", + """- Fold 3 poppers into dough pocket""", + ), + ( + "Assemble Popper Op", + "Food Prep Table 1", + "5", + """- Top dough bite with fruit""", + ), + ( + "Assemble Combination Product", + "Food Prep Table 1", + "5", + """- Tower: package one pie and one pocket, and one popper + - Pocketful of Bay: package one pocket with two poppers""", + ), +] + +items = [ + { + "item_code": "Ambrosia Pie", + "item_group": "Baked Goods", + "uom": "Nos", + "weight_per_unit": 7.5, + "weight_uom": "Pound", + "item_price": 11.00, + "default_warehouse": "Refrigerated Display - APC", + "description": "

Ambrosia Pie is the marquee product of Ambrosia Pie Company. A filling of heavenly cloudberries pair perfectly with the tart hairless rambutan, finished with drizzles of tayberry nectar. It's a feast fit for Mt Olympus!

", + }, + { + "item_code": "Double Plum Pie", + "uom": "Nos", + "weight_per_unit": 8, + "weight_uom": "Pound", + "item_group": "Baked Goods", + "item_price": 10.50, + "default_warehouse": "Refrigerated Display - APC", + "description": "

Double the fun and double the flavor with our Double Plum Pie! We combine damson and cocoplums in a daring tropical-meets-temperate filling. Forbidden fruit never tasted this good.

", + }, + { + "item_code": "Gooseberry Pie", + "uom": "Nos", + "weight_per_unit": 8.5, + "weight_uom": "Pound", + "item_group": "Baked Goods", + "item_price": 12.00, + "default_warehouse": "Refrigerated Display - APC", + "description": "

Our delicious take on the traditional gooseberry pie that tastes like the holidays. This classic pie is best shared with the ones you love.

", + }, + { + "item_code": "Kaduka Key Lime Pie", + "item_group": "Baked Goods", + "uom": "Nos", + "weight_per_unit": 9, + "weight_uom": "Pound", + "item_price": 11.50, + "default_warehouse": "Refrigerated Display - APC", + "description": "

Take your tastebuds on an adventure with this whimsical twist on the classic Key Lime pie. Made with kaduka limes and the exotic limequat, this seasonal pie is sure to satisfy even the most weary culinary explorer. Grab it when you can - it's only available April through September.

", + }, + { + "item_code": "Tower of Bay-bel", + "uom": "Nos", + "item_group": "Baked Goods", + "item_price": 20.00, + "default_warehouse": "Refrigerated Display - APC", + "description": "

Reach for the stars with this epic all-things-bayberry dessert that stacks a Bayberry Pocket on top of our Bayberry Pie.

", + }, + { + "item_code": "Pocketful of Bay", + "uom": "Nos", + "item_group": "Baked Goods", + "item_price": 12.00, + "default_warehouse": "Refrigerated Display - APC", + "description": "

Try this delightful combination of a Bayberry Pocket and two additional Bayberry Poppers.

", + }, + { + "item_code": "Bayberry Pie", + "uom": "Nos", + "item_group": "Sub Assemblies", + # "item_price": 11.00, # can a finished good be included as sub-assembly for another good? + "default_warehouse": "Refrigerated Display - APC", + "description": "

This pie features the sweet and scrumptious bayberry and is sure to be a crowd-pleaser.

", + }, + { + "item_code": "Bayberry Pocket", + "uom": "Nos", + "item_group": "Sub Assemblies", + # "item_price": 8.00, + "default_warehouse": "Refrigerated Display - APC", + "description": "

Need a little more than one popper? The Bayberry Pocket is a tasty dough pocket stuffed with several Bayberry Poppers.

", + }, + { + "item_code": "Bayberry Popper", + "uom": "Nos", + "item_group": "Sub Assemblies", + # "item_price": 3.00, + "default_warehouse": "Refrigerated Display - APC", + "description": "

Part cookie, part tart, these bite-sized treats will bring a little sweetness to your day.

", + }, + { + "item_code": "Ambrosia Pie Filling", + "uom": "Cup", + "item_group": "Sub Assemblies", + "default_warehouse": "Refrigerator - APC", + "description": "Ambrosia Pie Filling", + }, + { + "item_code": "Double Plum Pie Filling", + "uom": "Cup", + "item_group": "Sub Assemblies", + "default_warehouse": "Refrigerator - APC", + "description": "Double Plum Pie Filling", + }, + { + "item_code": "Gooseberry Pie Filling", + "uom": "Cup", + "description": "Gooseberry Pie Filling", + "item_group": "Sub Assemblies", + "default_warehouse": "Refrigerator - APC", + }, + { + "item_code": "Bayberry Pie Filling", + "uom": "Cup", + "description": "Bayberry Pie Filling", + "item_group": "Sub Assemblies", + "default_warehouse": "Refrigerator - APC", + }, + { + "item_code": "Kaduka Key Lime Pie Filling", + "item_group": "Sub Assemblies", + "default_warehouse": "Refrigerator - APC", + "uom": "Cup", + "description": "Kaduka Key Lime Pie Filling", + }, + { + "item_code": "Pie Crust", + "uom": "Nos", + "description": "Pie Crust", + "item_group": "Sub Assemblies", + "default_warehouse": "Refrigerator - APC", + "is_sub_contracted_item": 1, + "item_price": 2.00, + "default_supplier": "", + "supplier": "", + "valuation_rate": 3.0196, + "uom_conversion_detail": {"Hour": 20}, + }, + { + "item_code": "Pie Crust Service per Crust", + "uom": "Nos", + "description": "Subcontracted pie crust manufacturing service. Item price is per crust.", + "item_group": "Sub Assemblies", + "default_warehouse": "Credible Contract Baking - APC", + "is_sub_contracted_item": 1, + "is_stock_item": 0, + "item_price": 2.00, + "default_supplier": "Credible Contract Baking", + "supplier": "Credible Contract Baking", + }, + { + "item_code": "Pie Crust Service per Hour", + "uom": "Hour", + "description": "Subcontracted pie crust manufacturing service. Item price is per hour.", + "item_group": "Sub Assemblies", + "default_warehouse": "Credible Contract Baking - APC", + "is_sub_contracted_item": 1, + "is_stock_item": 0, + "item_price": 40.00, # Assumes 5 crusts takes 15 mins (excluding chilling time), or 20 crusts/hour at rate of $2.00/crust + "default_supplier": "Credible Contract Baking", + "supplier": "Credible Contract Baking", + }, + { + "item_code": "Cloudberry", + "uom": "Pound", + "weight_uom": "Pound", + "weight_per_unit": 1, + "description": "Cloudberry", + "item_group": "Ingredients", + "item_price": 0.65, + "default_warehouse": "Refrigerator - APC", + "supplier": ["Chelsea Fruit Co", "Southern Fruit Supply"], + }, + { + "item_code": "Cocoplum", + "uom": "Pound", + "weight_uom": "Pound", + "weight_per_unit": 1, + "description": "Cocoplum", + "item_group": "Ingredients", + "item_price": 0.35, + "default_warehouse": "Refrigerator - APC", + "supplier": ["Chelsea Fruit Co", "Southern Fruit Supply"], + }, + { + "item_code": "Damson Plum", + "uom": "Pound", + "weight_uom": "Pound", + "weight_per_unit": 1, + "description": "Damson Plum", + "item_group": "Ingredients", + "item_price": 0.85, + "default_warehouse": "Refrigerator - APC", + "supplier": ["Chelsea Fruit Co", "Southern Fruit Supply"], + }, + { + "item_code": "Gooseberry", + "uom": "Pound", + "weight_uom": "Pound", + "weight_per_unit": 1, + "description": "Gooseberry", + "item_group": "Ingredients", + "item_price": 0.99, + "default_warehouse": "Refrigerator - APC", + "supplier": ["Chelsea Fruit Co", "Southern Fruit Supply"], + }, + { + "item_code": "Hairless Rambutan", + "uom": "Pound", + "weight_uom": "Pound", + "weight_per_unit": 1, + "description": "Hairless Rambutan", + "item_price": 0.50, + "item_group": "Ingredients", + "default_warehouse": "Storeroom - APC", + "supplier": ["Chelsea Fruit Co", "Southern Fruit Supply"], + }, + { + "item_code": "Kaduka Lime", + "uom": "Pound", + "weight_uom": "Pound", + "weight_per_unit": 1, + "description": "Kaduka Lime", + "item_group": "Ingredients", + "item_price": 0.89, + "default_warehouse": "Refrigerator - APC", + "supplier": ["Chelsea Fruit Co", "Southern Fruit Supply"], + }, + { + "item_code": "Limequat", + "uom": "Pound", + "weight_uom": "Pound", + "weight_per_unit": 1, + "description": "Limequat", + "item_group": "Ingredients", + "item_price": 0.75, + "default_warehouse": "Refrigerator - APC", + "supplier": ["Chelsea Fruit Co", "Southern Fruit Supply"], + }, + { + "item_code": "Tayberry", + "uom": "Pound", + "weight_uom": "Pound", + "weight_per_unit": 1, + "description": "Tayberry", + "item_group": "Ingredients", + "item_price": 0.85, + "default_warehouse": "Refrigerator - APC", + "supplier": ["Chelsea Fruit Co", "Southern Fruit Supply"], + }, + { + "item_code": "Bayberry", + "uom": "Pound", + "weight_uom": "Pound", + "weight_per_unit": 1, + "description": "Bayberry", + "item_group": "Ingredients", + "item_price": 0.45, + "default_warehouse": "Refrigerator - APC", + "supplier": ["Chelsea Fruit Co", "Southern Fruit Supply"], + }, + { + "item_code": "Butter", + "uom": "Pound", + "weight_uom": "Pound", + "weight_per_unit": 1, + "description": "Butter", + "item_group": "Ingredients", + "item_price": 4.5, + "default_warehouse": "Refrigerator - APC", + "supplier": [ + "Freedom Provisions", + "Chelsea Fruit Co", + ], + }, + { + "item_code": "Cornstarch", + "uom": "Pound", + "weight_uom": "Pound", + "weight_per_unit": 1, + "description": "Cornstarch", + "item_group": "Ingredients", + "item_price": 0.52, + "default_warehouse": "Storeroom - APC", + "supplier": "Freedom Provisions", + }, + { + "item_code": "Ice Water", + "uom": "Cup", + "weight_uom": "Pound", + "weight_per_unit": 0.52, + "description": "Ice Water - necessary for pie crusts", + "item_group": "Ingredients", + "item_price": 0.01, + "default_warehouse": "Refrigerator - APC", + "available_in_house": 1, + "opening_qty": 50, + }, + { + "item_code": "Flour", + "uom": "Pound", + "weight_uom": "Pound", + "weight_per_unit": 1, + "description": "Flour", + "item_group": "Ingredients", + "item_price": 0.66, + "default_warehouse": "Storeroom - APC", + "supplier": "Freedom Provisions", + }, + { + "item_code": "Pie Box", + "uom": "Nos", + "description": "Pie Box", + "item_group": "Bakery Supplies", + "item_price": 0.4, + "default_warehouse": "Storeroom - APC", + "supplier": ["Freedom Provisions", "Unity Bakery Supply"], + }, + { + "item_code": "Pie Tin", + "uom": "Nos", + "description": "Pie Tin", + "item_price": 0.18, + "item_group": "Bakery Supplies", + "default_warehouse": "Storeroom - APC", + "supplier": ["Freedom Provisions", "Unity Bakery Supply"], + }, + { + "item_code": "Parchment Paper", + "uom": "Nos", + "description": "Parchment Paper", + "item_group": "Bakery Supplies", + "item_price": 0.02, + "default_warehouse": "Storeroom - APC", + "supplier": ["Freedom Provisions", "Unity Bakery Supply"], + "uom_conversion_detail": {"Box": 100}, + }, + { + "item_code": "Salt", + "uom": "Pound", + "weight_uom": "Pound", + "weight_per_unit": 1, + "description": "Salt", + "item_group": "Ingredients", + "item_price": 0.36, + "default_warehouse": "Storeroom - APC", + "supplier": "Freedom Provisions", + }, + { + "item_code": "Sugar", + "uom": "Pound", + "weight_uom": "Pound", + "weight_per_unit": 1, + "description": "Sugar", + "item_group": "Ingredients", + "item_price": 0.60, + "default_warehouse": "Storeroom - APC", + "supplier": "Freedom Provisions", + }, + { + "item_code": "Water", + "uom": "Cup", + "weight_uom": "Pound", + "weight_per_unit": 0.52, + "item_price": 0.05, + "description": "Water", + "item_group": "Ingredients", + "default_warehouse": "Kitchen - APC", + "available_in_house": 1, + "opening_qty": 50, + }, +] + +boms = [ + { + "item": "Tower of Bay-bel", + "quantity": 5.0, + "uom": "Nos", + "items": [ + {"item_code": "Bayberry Pie", "qty": 5.0, "qty_consumed_per_unit": 1.0, "uom": "Nos"}, + {"item_code": "Bayberry Pocket", "qty": 5.0, "qty_consumed_per_unit": 1.0, "uom": "Nos"}, + ], + "operations": [ + { + "batch_size": 5, + "operation": "Assemble Combination Product", + "time_in_mins": 2.0, + "workstation": "Food Prep Table 1", + }, + ], + }, + { + "item": "Pocketful of Bay", + "quantity": 5.0, + "uom": "Nos", + "items": [ + {"item_code": "Bayberry Pocket", "qty": 5.0, "qty_consumed_per_unit": 1.0, "uom": "Nos"}, + {"item_code": "Bayberry Popper", "qty": 10.0, "qty_consumed_per_unit": 2.0, "uom": "Nos"}, + {"item_code": "Pie Box", "qty": 5.0, "qty_consumed_per_unit": 1.0, "uom": "Nos"}, + ], + "operations": [ + { + "batch_size": 5, + "operation": "Assemble Combination Product", + "time_in_mins": 2.0, + "workstation": "Food Prep Table 1", + }, + ], + }, + { + "item": "Bayberry Pocket", + "quantity": 5.0, + "uom": "Nos", + "items": [ + {"item_code": "Flour", "qty": 1.5, "qty_consumed_per_unit": 0.3, "uom": "Pound"}, + {"item_code": "Butter", "qty": 0.75, "qty_consumed_per_unit": 0.15, "uom": "Pound"}, + {"item_code": "Sugar", "qty": 0.1, "qty_consumed_per_unit": 0.02, "uom": "Pound"}, + {"item_code": "Bayberry Popper", "qty": 15.0, "qty_consumed_per_unit": 3.0, "uom": "Nos"}, + ], + "operations": [ + { + "batch_size": 5, + "operation": "Mix Dough Op", + "time_in_mins": 5.0, + "workstation": "Mixer Station", + }, + { + "batch_size": 5, + "operation": "Assemble Pocket Op", + "time_in_mins": 2.0, + "workstation": "Food Prep Table 1", + }, + ], + }, + { + "item": "Bayberry Popper", + "quantity": 5.0, + "uom": "Nos", + "items": [ + {"item_code": "Flour", "qty": 0.5, "qty_consumed_per_unit": 0.1, "uom": "Pound"}, + {"item_code": "Butter", "qty": 0.25, "qty_consumed_per_unit": 0.05, "uom": "Pound"}, + {"item_code": "Sugar", "qty": 0.05, "qty_consumed_per_unit": 0.01, "uom": "Pound"}, + {"item_code": "Bayberry", "qty": 1.0, "qty_consumed_per_unit": 0.2, "uom": "Pound"}, + ], + "operations": [ + { + "batch_size": 5, + "operation": "Mix Dough Op", + "time_in_mins": 5.0, + "workstation": "Mixer Station", + }, + { + "batch_size": 5, + "operation": "Assemble Popper Op", + "time_in_mins": 1.0, + "workstation": "Food Prep Table 1", + }, + ], + }, + { + "item": "Bayberry Pie", + "quantity": 5.0, + "uom": "Nos", + "items": [ + {"item_code": "Pie Crust", "qty": 5.0, "qty_consumed_per_unit": 1.0, "uom": "Nos"}, + { + "item_code": "Bayberry Pie Filling", + "qty": 20.0, + "qty_consumed_per_unit": 4.0, + "uom": "Cup", + }, + {"item_code": "Pie Box", "qty": 5.0, "qty_consumed_per_unit": 1.0, "uom": "Nos"}, + ], + "operations": [ + { + "batch_size": 5, + "operation": "Assemble Pie Op", + "time_in_mins": 10.0, + "workstation": "Food Prep Table 2", + }, + {"batch_size": 1, "operation": "Bake Op", "time_in_mins": 50.0, "workstation": "Oven Station"}, + { + "batch_size": 1, + "operation": "Cool Pie Op", + "time_in_mins": 30.0, + "workstation": "Cooling Racks Station", + }, + { + "batch_size": 5, + "operation": "Box Pie Op", + "time_in_mins": 5.0, + "workstation": "Packaging Station", + }, + ], + }, + { + "item": "Double Plum Pie", + "quantity": 5.0, + "uom": "Nos", + "items": [ + {"item_code": "Pie Crust", "qty": 5.0, "qty_consumed_per_unit": 1.0, "uom": "Nos"}, + { + "item_code": "Double Plum Pie Filling", + "qty": 20.0, + "qty_consumed_per_unit": 4.0, + "uom": "Cup", + }, + {"item_code": "Pie Box", "qty": 5.0, "qty_consumed_per_unit": 1.0, "uom": "Nos"}, + ], + "operations": [ + { + "batch_size": 5, + "operation": "Assemble Pie Op", + "time_in_mins": 10.0, + "workstation": "Food Prep Table 2", + }, + {"batch_size": 1, "operation": "Bake Op", "time_in_mins": 50.0, "workstation": "Oven Station"}, + { + "batch_size": 1, + "operation": "Cool Pie Op", + "time_in_mins": 30.0, + "workstation": "Cooling Racks Station", + }, + { + "batch_size": 5, + "operation": "Box Pie Op", + "time_in_mins": 5.0, + "workstation": "Packaging Station", + }, + ], + }, + { + "item": "Kaduka Key Lime Pie", + "quantity": 5.0, + "uom": "Nos", + "items": [ + {"item_code": "Pie Crust", "qty": 5.0, "qty_consumed_per_unit": 1.0, "uom": "Nos"}, + { + "item_code": "Kaduka Key Lime Pie Filling", + "qty": 20.0, + "qty_consumed_per_unit": 4.0, + "uom": "Cup", + }, + {"item_code": "Pie Box", "qty": 5.0, "qty_consumed_per_unit": 1.0, "uom": "Nos"}, + ], + "operations": [ + { + "batch_size": 5, + "operation": "Assemble Pie Op", + "time_in_mins": 10.0, + "workstation": "Food Prep Table 2", + }, + {"batch_size": 1, "operation": "Bake Op", "time_in_mins": 50.0, "workstation": "Oven Station"}, + { + "batch_size": 1, + "operation": "Cool Pie Op", + "time_in_mins": 30.0, + "workstation": "Cooling Racks Station", + }, + { + "batch_size": 5, + "operation": "Box Pie Op", + "time_in_mins": 5.0, + "workstation": "Packaging Station", + }, + ], + }, + { + "item": "Gooseberry Pie", + "quantity": 5.0, + "uom": "Nos", + "items": [ + {"item_code": "Pie Crust", "qty": 5.0, "qty_consumed_per_unit": 1.0, "uom": "Nos"}, + { + "item_code": "Gooseberry Pie Filling", + "qty": 20.0, + "qty_consumed_per_unit": 4.0, + "uom": "Cup", + }, + {"item_code": "Pie Box", "qty": 5.0, "qty_consumed_per_unit": 1.0, "uom": "Nos"}, + ], + "operations": [ + { + "batch_size": 5, + "operation": "Assemble Pie Op", + "time_in_mins": 10.0, + "workstation": "Food Prep Table 2", + }, + {"batch_size": 1, "operation": "Bake Op", "time_in_mins": 50.0, "workstation": "Oven Station"}, + { + "batch_size": 1, + "operation": "Cool Pie Op", + "time_in_mins": 30.0, + "workstation": "Cooling Racks Station", + }, + { + "batch_size": 5, + "operation": "Box Pie Op", + "time_in_mins": 5.0, + "workstation": "Packaging Station", + }, + ], + }, + { + "item": "Ambrosia Pie", + "quantity": 5.0, + "uom": "Nos", + "overproduction_percentage_for_work_order": 100, + "items": [ + {"item_code": "Pie Crust", "qty": 5.0, "qty_consumed_per_unit": 1.0, "uom": "Nos"}, + {"item_code": "Ambrosia Pie Filling", "qty": 20.0, "qty_consumed_per_unit": 4.0, "uom": "Cup"}, + {"item_code": "Pie Box", "qty": 5.0, "qty_consumed_per_unit": 1.0, "uom": "Nos"}, + ], + "operations": [ + { + "batch_size": 5, + "operation": "Assemble Pie Op", + "time_in_mins": 10.0, + "workstation": "Food Prep Table 2", + }, + {"batch_size": 1, "operation": "Bake Op", "time_in_mins": 50.0, "workstation": "Oven Station"}, + { + "batch_size": 1, + "operation": "Cool Pie Op", + "time_in_mins": 30.0, + "workstation": "Cooling Racks Station", + }, + { + "batch_size": 5, + "operation": "Box Pie Op", + "time_in_mins": 5.0, + "workstation": "Packaging Station", + }, + ], + }, + { + "item": "Bayberry Pie Filling", + "quantity": 20.0, + "uom": "Cup", + "items": [ + {"item_code": "Sugar", "qty": 0.5, "qty_consumed_per_unit": 0.025, "uom": "Pound"}, + {"item_code": "Cornstarch", "qty": 0.1, "qty_consumed_per_unit": 0.005, "uom": "Pound"}, + {"item_code": "Water", "qty": 1.25, "qty_consumed_per_unit": 0.0625, "uom": "Cup"}, + {"item_code": "Butter", "qty": 0.313, "qty_consumed_per_unit": 0.01565, "uom": "Pound"}, + {"item_code": "Bayberry", "qty": 15.0, "qty_consumed_per_unit": 0.05025, "uom": "Pound"}, + ], + "operations": [ + { + "batch_size": 5, + "operation": "Gather Pie Filling Ingredients", + "time_in_mins": 5.0, + "workstation": "Food Prep Table 1", + }, + { + "batch_size": 5, + "operation": "Cook Pie Filling Operation", + "time_in_mins": 15.0, + "workstation": "Range Station", + }, + ], + }, + { + "item": "Double Plum Pie Filling", + "quantity": 20.0, + "uom": "Cup", + "items": [ + {"item_code": "Sugar", "qty": 0.5, "qty_consumed_per_unit": 0.025, "uom": "Pound"}, + {"item_code": "Cornstarch", "qty": 0.1, "qty_consumed_per_unit": 0.005, "uom": "Pound"}, + {"item_code": "Water", "qty": 1.25, "qty_consumed_per_unit": 0.0625, "uom": "Cup"}, + {"item_code": "Butter", "qty": 0.313, "qty_consumed_per_unit": 0.01565, "uom": "Pound"}, + {"item_code": "Cocoplum", "qty": 7.5, "qty_consumed_per_unit": 0.02515, "uom": "Pound"}, + {"item_code": "Damson Plum", "qty": 7.5, "qty_consumed_per_unit": 0.02515, "uom": "Pound"}, + ], + "operations": [ + { + "batch_size": 5, + "operation": "Gather Pie Filling Ingredients", + "time_in_mins": 5.0, + "workstation": "Food Prep Table 1", + }, + { + "batch_size": 5, + "operation": "Cook Pie Filling Operation", + "time_in_mins": 15.0, + "workstation": "Range Station", + }, + ], + }, + { + "item": "Kaduka Key Lime Pie Filling", + "quantity": 20.0, + "uom": "Cup", + "items": [ + {"item_code": "Sugar", "qty": 0.5, "qty_consumed_per_unit": 0.025, "uom": "Pound"}, + {"item_code": "Cornstarch", "qty": 0.1, "qty_consumed_per_unit": 0.005, "uom": "Pound"}, + {"item_code": "Water", "qty": 1.25, "qty_consumed_per_unit": 0.0625, "uom": "Cup"}, + {"item_code": "Butter", "qty": 0.313, "qty_consumed_per_unit": 0.01565, "uom": "Pound"}, + {"item_code": "Kaduka Lime", "qty": 10.0, "qty_consumed_per_unit": 0.0335, "uom": "Pound"}, + {"item_code": "Limequat", "qty": 5.0, "qty_consumed_per_unit": 0.01675, "uom": "Pound"}, + ], + "operations": [ + { + "batch_size": 5, + "operation": "Gather Pie Filling Ingredients", + "time_in_mins": 5.0, + "workstation": "Food Prep Table 1", + }, + { + "batch_size": 5, + "operation": "Cook Pie Filling Operation", + "time_in_mins": 15.0, + "workstation": "Range Station", + }, + ], + }, + { + "item": "Gooseberry Pie Filling", + "quantity": 20.0, + "uom": "Cup", + "items": [ + {"item_code": "Sugar", "qty": 0.5, "qty_consumed_per_unit": 0.025, "uom": "Pound"}, + {"item_code": "Cornstarch", "qty": 0.1, "qty_consumed_per_unit": 0.005, "uom": "Pound"}, + {"item_code": "Water", "qty": 1.25, "qty_consumed_per_unit": 0.0625, "uom": "Cup"}, + {"item_code": "Butter", "qty": 0.313, "qty_consumed_per_unit": 0.01565, "uom": "Pound"}, + {"item_code": "Gooseberry", "qty": 15.0, "qty_consumed_per_unit": 0.05025, "uom": "Pound"}, + ], + "operations": [ + { + "batch_size": 5, + "operation": "Gather Pie Filling Ingredients", + "time_in_mins": 5.0, + "workstation": "Food Prep Table 1", + }, + { + "batch_size": 5, + "operation": "Cook Pie Filling Operation", + "time_in_mins": 15.0, + "workstation": "Range Station", + }, + ], + }, + { + "item": "Ambrosia Pie Filling", + "quantity": 20.0, + "uom": "Cup", + "items": [ + {"item_code": "Sugar", "qty": 0.5, "qty_consumed_per_unit": 0.025, "uom": "Pound"}, + {"item_code": "Cornstarch", "qty": 0.1, "qty_consumed_per_unit": 0.005, "uom": "Pound"}, + {"item_code": "Butter", "qty": 0.313, "qty_consumed_per_unit": 0.01565, "uom": "Pound"}, + { + "item_code": "Hairless Rambutan", + "qty": 5.0, + "qty_consumed_per_unit": 0.01675, + "uom": "Pound", + }, + {"item_code": "Tayberry", "qty": 2.5, "qty_consumed_per_unit": 0.0084, "uom": "Pound"}, + {"item_code": "Cloudberry", "qty": 7.5, "qty_consumed_per_unit": 0.02515, "uom": "Pound"}, + {"item_code": "Water", "qty": 1.25, "qty_consumed_per_unit": 0.0625, "uom": "Cup"}, + ], + "operations": [ + { + "batch_size": 5, + "operation": "Gather Pie Filling Ingredients", + "time_in_mins": 5.0, + "workstation": "Food Prep Table 1", + }, + { + "batch_size": 5, + "operation": "Cook Pie Filling Operation", + "time_in_mins": 15.0, + "workstation": "Range Station", + }, + ], + }, + { + "item": "Pie Crust", # Subcontracted BOM + "quantity": 5.0, + "uom": "Nos", + "is_default": 0, + "is_subcontracted": 1, + "with_operations": 0, + "items": [ + {"item_code": "Flour", "qty": 4.25, "qty_consumed_per_unit": 0.85, "uom": "Pound"}, + {"item_code": "Butter", "qty": 2.5, "qty_consumed_per_unit": 0.5, "uom": "Pound"}, + # {"item_code": "Ice Water", "qty": 2.5, "qty_consumed_per_unit": 0.5, "uom": "Cup"}, + {"item_code": "Salt", "qty": 0.05, "qty_consumed_per_unit": 0.01, "uom": "Pound"}, + {"item_code": "Parchment Paper", "qty": 5.0, "qty_consumed_per_unit": 1.0, "uom": "Nos"}, + {"item_code": "Pie Tin", "qty": 5.0, "qty_consumed_per_unit": 1.0, "uom": "Nos"}, + ], + "operations": [], # Subcontracted item -> operations done by supplier + }, + { + "item": "Pie Crust", # In-house BOM + "quantity": 5.0, + "uom": "Nos", + "items": [ + {"item_code": "Flour", "qty": 4.25, "qty_consumed_per_unit": 0.85, "uom": "Pound"}, + {"item_code": "Butter", "qty": 2.5, "qty_consumed_per_unit": 0.5, "uom": "Pound"}, + {"item_code": "Ice Water", "qty": 2.5, "qty_consumed_per_unit": 0.5, "uom": "Cup"}, + {"item_code": "Salt", "qty": 0.05, "qty_consumed_per_unit": 0.01, "uom": "Pound"}, + {"item_code": "Parchment Paper", "qty": 5.0, "qty_consumed_per_unit": 1.0, "uom": "Nos"}, + {"item_code": "Pie Tin", "qty": 5.0, "qty_consumed_per_unit": 1.0, "uom": "Nos"}, + ], + "operations": [ + { + "batch_size": 5, + "operation": "Gather Pie Crust Ingredients", + "time_in_mins": 5.0, + "workstation": "Food Prep Table 2", + }, + { + "batch_size": 5, + "operation": "Mix Dough Op", + "time_in_mins": 5.0, + "workstation": "Mixer Station", + }, + { + "batch_size": 1, + "operation": "Divide Dough Op", + "time_in_mins": 2.0, + "workstation": "Food Prep Table 2", + }, + { + "batch_size": 1, + "operation": "Chill Pie Crust Op", + "time_in_mins": 30.0, + "workstation": "Refrigerator Station", + }, + { + "batch_size": 5, + "operation": "Roll Pie Crust Op", + "time_in_mins": 10.0, + "workstation": "Food Prep Table 2", + }, + ], + }, +] + +customers = [ + "Almacs Food Group", + "Beans and Dreams Roasters", + "Cafe 27 Cafeteria", + "Capital Grille Restaurant Group", + "Downtown Deli", + "Draws Groceries", + "Grab n Go Bodega", + "Grand North Station Baking Co", + "Happy Basket Food Distribution Group", + "Jitter Cafe", + "Longwoods Sandwich Shop", + "Midtown Munchies Inc", + "My Way Cup Coffee", + "Nom Nom Cafe", + "Round the World Donut Shop", + "Sand Street Deli", + "Starfood Cafe", + "Terrywood Terminal Bakery Inc", + "TransAmerica Bank Cafeteria", + "Whole Harvest Grocery Group", +] + +specifications = [ + { + "dt": "Item", + "name": "Items", + "apply_on": "", + "enabled": 1, + "attributes": [ + { + "attribute_name": "Color", + "applied_on": "Item", + "component": "FacetedSearchColorPicker", + }, + { + "attribute_name": "Weight", + "applied_on": "Item", + "field": "weight_per_unit", + "numeric_values": 1, + "component": "FacetedSearchNumericRange", + }, + { + "attribute_name": "Brand", + "applied_on": "Item", + "field": "brand", + "component": "AttributeFilter", + }, + ], + }, + { + "dt": "Item Group", + "name": "Baked Goods", + "apply_on": "Baked Goods", + "enabled": 1, + "attributes": [ + { + "attribute_name": "Price", + "applied_on": "Item", + "numeric_values": 1, + "component": "FacetedSearchNumericRange", + }, + {"attribute_name": "Fruits", "applied_on": "Item", "component": "AttributeFilter"}, + { + "attribute_name": "Shelf Life", + "applied_on": "Item", + "field": "shelf_life_in_days", + "numeric_values": 1, + "component": "FacetedSearchNumericRange", + }, + { + "attribute_name": "EOL", + "applied_on": "Item", + "field": "end_of_life", + "date_values": 1, + "component": "FacetedSearchDateRange", + }, + ], + }, +] + + +attributes = { + "Ambrosia Pie": { + "Fruits": ["Hairless Rambutan", "Cloudberry", "Tayberry"], + "Price": 11.00, + "Color": ["Blue", "Red"], + "Brand": "Chelsea Fruit Co", + }, + "Double Plum Pie": { + "Fruits": ["Cocoplum", "Damson Plum"], + "Price": 10.50, + "Color": ["Purple"], + "Brand": "Chelsea Fruit Co", + }, + "Gooseberry Pie": { + "Fruits": "Gooseberry", + "Price": 12.00, + "Color": ["Yellow"], + "Brand": "Chelsea Fruit Co", + }, + "Kaduka Key Lime Pie": { + "Fruits": ["Kaduka Lime", "Limequat"], + "Price": 11.50, + "Color": ["Green", "Yellow"], + "Brand": "Chelsea Fruit Co", + }, + "Tayberry": { + "Color": ["Red"], + }, + "Limequat": { + "Color": ["Yellow", "Green"], + }, + "Kaduka Lime": { + "Color": ["Green"], + }, + "Hairless Rambutan": { + "Color": ["Red"], + }, + "Gooseberry": { + "Color": ["Yellow"], + }, + "Damson Plum": { + "Color": ["Purple"], + }, + "Cocoplum": { + "Color": ["Purple", "Black"], + }, + "Bayberry": { + "Color": ["Red", "Green", "Blue"], + }, + "Sugar": { + "Color": ["White"], + }, + "Salt": { + "Color": ["White"], + }, + "Flour": { + "Color": ["White"], + }, + "Cornstarch": { + "Color": ["White"], + }, + "Butter": { + "Color": ["Yellow"], + }, + "Cloudberry": { + "Color": ["Yellow", "Red"], + }, +} diff --git a/inventory_tools/tests/setup.py b/inventory_tools/tests/setup.py index 5c61c10..e83e975 100644 --- a/inventory_tools/tests/setup.py +++ b/inventory_tools/tests/setup.py @@ -1,809 +1,3 @@ -<<<<<<< HEAD -import datetime -import types -from itertools import groupby - -import frappe -from erpnext.accounts.doctype.account.account import update_account_number -from erpnext.e_commerce.doctype.website_item.website_item import make_website_item -from erpnext.manufacturing.doctype.production_plan.production_plan import ( - get_items_for_material_requests, -) -from erpnext.setup.utils import enable_all_roles_and_domains, set_defaults_for_tests -from erpnext.stock.get_item_details import get_item_details -from frappe.desk.page.setup_wizard.setup_wizard import setup_complete -from frappe.utils.data import add_months, flt, getdate, nowdate - -from inventory_tools.tests.fixtures import ( - attributes, - boms, - customers, - items, - operations, - specifications, - suppliers, - workstations, -) - - -def before_test(): - frappe.clear_cache() - setup_complete( - { - "currency": "USD", - "full_name": "Administrator", - "company_name": "Ambrosia Pie Company", - "timezone": "America/New_York", - "company_abbr": "APC", - "domains": ["Distribution"], - "country": "United States", - "fy_start_date": getdate().replace(month=1, day=1).isoformat(), - "fy_end_date": getdate().replace(month=12, day=31).isoformat(), - "language": "english", - "company_tagline": "Ambrosia Pie Company", - "email": "support@agritheory.dev", - "password": "admin", - "chart_of_accounts": "Standard with Numbers", - "bank_account": "Primary Checking", - } - ) - set_defaults_for_tests() - for modu in frappe.get_all("Module Onboarding"): - frappe.db.set_value("Module Onboarding", modu, "is_complete", 1) - frappe.set_value("Website Settings", "Website Settings", "home_page", "login") - frappe.db.commit() - create_test_data() - - -def create_test_data(): - settings = frappe._dict( - { - "day": getdate().replace(month=1, day=1), - "company": "Ambrosia Pie Company", - "company_account": frappe.get_value( - "Account", - { - "account_type": "Bank", - "company": frappe.defaults.get_defaults().get("company"), - "is_group": 0, - }, - ), - } - ) - company_address = frappe.new_doc("Address") - company_address.title = settings.company - company_address.address_type = "Office" - company_address.address_line1 = "67C Sweeny Street" - company_address.city = "Chelsea" - company_address.state = "MA" - company_address.pincode = "89077" - company_address.is_your_company_address = 1 - company_address.append("links", {"link_doctype": "Company", "link_name": settings.company}) - company_address.save() - cfc = frappe.new_doc("Company") - cfc.company_name = "Chelsea Fruit Co" - cfc.default_currency = "USD" - cfc.create_chart_of_accounts_based_on = "Existing Company" - cfc.existing_company = settings.company - cfc.abbr = "CFC" - cfc.save() - - frappe.db.set_single_value("Stock Settings", "valuation_method", "Moving Average") - frappe.db.set_single_value("Stock Settings", "default_warehouse", "") - create_warehouses(settings) - setup_manufacturing_settings(settings) - create_workstations() - create_operations() - create_item_groups(settings) - create_price_lists(settings) - create_suppliers(settings) - create_customers(settings) - create_items(settings) - create_boms(settings) - prod_plan_from_doc = "Sales Order" - if prod_plan_from_doc == "Sales Order": - create_sales_order(settings) - else: - create_material_request(settings) - create_production_plan(settings, prod_plan_from_doc) - create_fruit_material_request(settings) - create_quotations(settings) - create_specifications(settings) - - -def create_suppliers(settings): - if not frappe.db.exists("Supplier Group", "Bakery"): - bsg = frappe.new_doc("Supplier Group") - bsg.supplier_group_name = "Bakery" - bsg.parent_supplier_group = "All Supplier Groups" - bsg.save() - - addresses = frappe._dict({}) - for supplier in suppliers: - biz = frappe.new_doc("Supplier") - biz.supplier_name = supplier[0] - biz.supplier_group = "Bakery" - biz.country = "United States" - biz.supplier_default_mode_of_payment = supplier[2] - if biz.supplier_default_mode_of_payment == "ACH/EFT": - biz.bank = "Local Bank" - biz.bank_account = "123456789" - biz.currency = "USD" - if biz.supplier_name == "Credible Contract Baking": - biz.append( - "subcontracting_defaults", - { - "company": settings.company, - "wip_warehouse": "Credible Contract Baking - APC", - "return_warehouse": "Baked Goods - APC", - }, - ) - biz.default_price_list = "Bakery Buying" - biz.save() - - existing_address = frappe.get_value("Address", {"address_line1": supplier[5]["address_line1"]}) - if not existing_address: - addr = frappe.new_doc("Address") - addr.address_title = f"{supplier[0]} - {supplier[5]['city']}" - addr.address_type = "Billing" - addr.address_line1 = supplier[5]["address_line1"] - addr.city = supplier[5]["city"] - addr.state = supplier[5]["state"] - addr.country = supplier[5]["country"] - addr.pincode = supplier[5]["pincode"] - else: - addr = frappe.get_doc("Address", existing_address) - addr.append("links", {"link_doctype": "Supplier", "link_name": supplier[0]}) - addr.save() - - -def create_customers(settings): - for customer_name in customers: - customer = frappe.new_doc("Customer") - customer.customer_name = customer_name - customer.customer_group = "Commercial" - customer.customer_type = "Company" - customer.territory = "United States" - customer.save() - - -def setup_manufacturing_settings(settings): - mfg_settings = frappe.get_doc("Manufacturing Settings", "Manufacturing Settings") - mfg_settings.material_consumption = 1 - mfg_settings.default_wip_warehouse = "Kitchen - APC" - mfg_settings.default_fg_warehouse = "Refrigerated Display - APC" - mfg_settings.overproduction_percentage_for_work_order = 5.00 - mfg_settings.job_card_excess_transfer = 1 - mfg_settings.save() - - if not frappe.db.exists( - "Account", {"account_name": "Work In Progress", "company": settings.company} - ): - wip = frappe.new_doc("Account") - wip.account_name = "Work in Progress" - wip.parent_account = "1400 - Stock Assets - APC" - wip.account_number = "1420" - wip.company = settings.company - wip.currency = "USD" - wip.report_type = "Balance Sheet" - wip.root_type = "Asset" - wip.save() - - frappe.set_value("Warehouse", "Kitchen - APC", "account", wip.name) - frappe.set_value( - "Inventory Tools Settings", settings.company, "enable_work_order_subcontracting", 1 - ) - frappe.set_value("Inventory Tools Settings", settings.company, "create_purchase_orders", 0) - frappe.set_value( - "Inventory Tools Settings", settings.company, "overproduction_percentage_for_work_order", 50 - ) - - -def create_workstations(): - for ws in workstations: - if frappe.db.exists("Workstation", ws[0]): - continue - work = frappe.new_doc("Workstation") - work.workstation_name = ws[0] - work.production_capacity = ws[1] - work.save() - - -def create_operations(): - for op in operations: - if frappe.db.exists("Operation", op[0]): - continue - oper = frappe.new_doc("Operation") - oper.name = op[0] - oper.workstation = op[1] - oper.batch_size = op[2] - oper.description = op[3] - if len(op) == 5: - for aw in op[4]: - oper.append( - "alternative_workstations", - { - "workstation": aw, - }, - ) - oper.save() - - -def create_item_groups(settings): - for ig_name in ( - "Baked Goods", - "Bakery Supplies", - "Ingredients", - "Bakery Equipment", - "Sub Assemblies", - ): - if frappe.db.exists("Item Group", ig_name): - continue - ig = frappe.new_doc("Item Group") - ig.item_group_name = ig_name - ig.parent_item_group = "All Item Groups" - ig.save() - - if not frappe.db.exists("Brand", "Ambrosia Pie Co"): - brand = frappe.new_doc("Brand") - brand.brand = "Ambrosia Pie Co" - brand.save() - - -def create_price_lists(settings): - if not frappe.db.exists("Price List", "Bakery Buying"): - pl = frappe.new_doc("Price List") - pl.price_list_name = "Bakery Buying" - pl.currency = "USD" - pl.buying = 1 - pl.append("countries", {"country": "United States"}) - pl.save() - - if not frappe.db.exists("Price List", "Bakery Wholesale"): - pl = frappe.new_doc("Price List") - pl.price_list_name = "Bakery Wholesale" - pl.currency = "USD" - pl.selling = 1 - pl.append("countries", {"country": "United States"}) - pl.save() - - if not frappe.db.exists("Pricing Rule", "Bakery Retail"): - pr = frappe.new_doc("Pricing Rule") - pr.title = "Bakery Retail" - pr.selling = 1 - pr.apply_on = "Item Group" - pr.company = settings.company - pr.margin_type = "Percentage" - pr.margin_rate_or_amount = 2.00 - pr.valid_from = settings.day - pr.for_price_list = "Bakery Wholesale" - pr.currency = "USD" - pr.append("item_groups", {"item_group": "Baked Goods"}) - pr.save() - - -def create_items(settings): - for item in items: - if frappe.db.exists("Item", item.get("item_code")): - continue - i = frappe.new_doc("Item") - i.item_code = i.item_name = item.get("item_code") - i.item_group = item.get("item_group") - i.stock_uom = item.get("uom") - i.description = item.get("description") - i.is_stock_item = 0 if item.get("is_stock_item") == 0 else 1 - i.include_item_in_manufacturing = 1 - i.valuation_rate = item.get("valuation_rate") or 0 - i.is_sub_contracted_item = item.get("is_sub_contracted_item") or 0 - i.default_warehouse = settings.get("warehouse") - i.weight_uom = item.get("weight_uom", "Pound") if i.is_stock_item else None - i.weight_per_unit = item.get("weight_per_unit") - i.default_material_request_type = ( - "Purchase" - if item.get("item_group") in ("Bakery Supplies", "Ingredients") - or item.get("is_sub_contracted_item") - else "Manufacture" - ) - i.valuation_method = "Moving Average" - if item.get("uom_conversion_detail"): - for uom, cf in item.get("uom_conversion_detail").items(): - i.append("uoms", {"uom": uom, "conversion_factor": cf}) - i.is_purchase_item = ( - 1 - if item.get("item_group") in ("Bakery Supplies", "Ingredients") - or item.get("is_sub_contracted_item") - else 0 - ) - i.is_sales_item = 1 if item.get("item_group") == "Baked Goods" else 0 - i.sales_uom = "Nos" if i.is_sales_item else None - i.shelf_life_in_days = 7 if i.is_sales_item else None - i.brand = "Ambrosia Pie Co" if i.is_sales_item else None - i.append( - "item_defaults", - { - "company": settings.company, - "default_warehouse": item.get("default_warehouse"), - "default_supplier": item.get("default_supplier"), - "requires_rfq": True if item.get("item_code") == "Cloudberry" else False, - }, - ) - if i.is_purchase_item and item.get("supplier"): - if isinstance(item.get("supplier"), list): - [i.append("supplier_items", {"supplier": s}) for s in item.get("supplier")] - else: - i.append("supplier_items", {"supplier": item.get("supplier")}) - i.save() - if item.get("item_price"): - ip = frappe.new_doc("Item Price") - ip.item_code = i.item_code - ip.uom = i.stock_uom - ip.price_list = "Bakery Wholesale" if i.is_sales_item else "Bakery Buying" - ip.buying = 1 - ip.valid_from = "2018-1-1" - ip.price_list_rate = item.get("item_price") - ip.save() - if item.get("available_in_house"): - se = frappe.new_doc("Stock Entry") - se.posting_date = settings.day - se.set_posting_time = 1 - se.stock_entry_type = "Material Receipt" - se.append( - "items", - { - "item_code": item.get("item_code"), - "t_warehouse": item.get("default_warehouse"), - "qty": item.get("opening_qty"), - "uom": item.get("uom"), - "stock_uom": item.get("uom"), - "conversion_factor": 1, - "basic_rate": item.get("item_price"), - "expense_account": "1910 - Temporary Opening - APC", - }, - ) - se.save() - se.submit() - if i.is_sales_item: - website_item = make_website_item(i, True) - website_item = frappe.get_doc("Website Item", website_item[0]) - website_item.route = f"products/{frappe.scrub(i.name)}" - website_item.save() - - -def create_warehouses(settings): - inventory_tools_settings = frappe.get_doc("Inventory Tools Settings", settings.company) - inventory_tools_settings.enable_work_order_subcontracting = 1 - inventory_tools_settings.create_purchase_orders = 0 - inventory_tools_settings.update_warehouse_path = 1 - inventory_tools_settings.save() - - warehouses = [item.get("default_warehouse") for item in items] - root_wh = frappe.get_value("Warehouse", {"company": settings.company, "is_group": 1}) - if frappe.db.exists("Warehouse", "Stores - APC"): - frappe.rename_doc("Warehouse", "Stores - APC", "Storeroom - APC", force=True) - if frappe.db.exists("Warehouse", "Finished Goods - APC"): - frappe.rename_doc("Warehouse", "Finished Goods - APC", "Baked Goods - APC", force=True) - frappe.set_value("Warehouse", "Baked Goods - APC", "is_group", 1) - for wh in frappe.get_all("Warehouse", {"company": settings.company}, ["name", "is_group"]): - if wh.name not in warehouses and not wh.is_group: - frappe.delete_doc("Warehouse", wh.name) - for item in items: - if frappe.db.exists("Warehouse", item.get("default_warehouse")): - continue - wh = frappe.new_doc("Warehouse") - wh.warehouse_name = item.get("default_warehouse").split(" - ")[0] - wh.parent_warehouse = root_wh - wh.company = settings.company - wh.save() - - wh = frappe.new_doc("Warehouse") - wh.warehouse_name = "Bakery Display" - wh.parent_warehouse = "Baked Goods - APC" - wh.company = settings.company - wh.save() - - wh = frappe.get_doc("Warehouse", "Refrigerated Display - APC") - wh.parent_warehouse = "Baked Goods - APC" - wh.save() - - -def create_boms(settings): - for bom in boms[::-1]: # reversed - if frappe.db.exists("BOM", {"item": bom.get("item")}) and bom.get("item") != "Pie Crust": - continue - b = frappe.new_doc("BOM") - b.item = bom.get("item") - b.quantity = bom.get("quantity") - b.uom = bom.get("uom") - b.company = settings.company - b.is_default = 0 if bom.get("is_default") == 0 else 1 - b.is_subcontracted = bom.get("is_subcontracted") or 0 - b.overproduction_percentage_for_work_order = bom.get( - "overproduction_percentage_for_work_order", None - ) - b.rm_cost_as_per = "Price List" - b.buying_price_list = "Bakery Buying" - b.currency = "USD" - b.with_operations = 0 if bom.get("with_operations") == 0 else 1 - for item in bom.get("items"): - b.append("items", {**item, "stock_uom": item.get("uom")}) - b.items[-1].bom_no = frappe.get_value("BOM", {"item": item.get("item_code")}) - for operation in bom.get("operations"): - b.append("operations", {**operation, "hour_rate": 15.00}) - b.save() - b.submit() - - -def create_sales_order(settings): - so = frappe.new_doc("Sales Order") - so.transaction_date = settings.day - so.customer = customers[0] - so.order_type = "Sales" - so.currency = "USD" - so.selling_price_list = "Bakery Wholesale" - so.append( - "items", - { - "item_code": "Ambrosia Pie", - "delivery_date": so.transaction_date, - "qty": 30, - "warehouse": "Refrigerated Display - APC", - }, - ) - so.append( - "items", - { - "item_code": "Double Plum Pie", - "delivery_date": so.transaction_date, - "qty": 30, - "warehouse": "Refrigerated Display - APC", - }, - ) - so.append( - "items", - { - "item_code": "Gooseberry Pie", - "delivery_date": so.transaction_date, - "qty": 10, - "warehouse": "Refrigerated Display - APC", - }, - ) - so.append( - "items", - { - "item_code": "Kaduka Key Lime Pie", - "delivery_date": so.transaction_date, - "qty": 10, - "warehouse": "Refrigerated Display - APC", - }, - ) - so.append( - "items", - { - "item_code": "Pocketful of Bay", - "delivery_date": so.transaction_date, - "qty": 10, - "warehouse": "Refrigerated Display - APC", - }, - ) - so.append( - "items", - { - "item_code": "Tower of Bay-bel", - "delivery_date": so.transaction_date, - "qty": 20, - "warehouse": "Refrigerated Display - APC", - }, - ) - so.save() - so.submit() - - -def create_material_request(settings): - mr = frappe.new_doc("Material Request") - mr.material_request_type = "Manufacture" - mr.schedule_date = mr.transaction_date = settings.day - mr.title = "Pies" - mr.company = settings.company - mr.append( - "items", - { - "item_code": "Ambrosia Pie", - "schedule_date": mr.schedule_date, - "qty": 40, - "warehouse": "Refrigerated Display - APC", - }, - ) - mr.append( - "items", - { - "item_code": "Double Plum Pie", - "schedule_date": mr.schedule_date, - "qty": 40, - "warehouse": "Refrigerated Display - APC", - }, - ) - mr.append( - "items", - { - "item_code": "Gooseberry Pie", - "schedule_date": mr.schedule_date, - "qty": 10, - "warehouse": "Refrigerated Display - APC", - }, - ) - mr.append( - "items", - { - "item_code": "Kaduka Key Lime Pie", - "schedule_date": mr.schedule_date, - "qty": 10, - "warehouse": "Refrigerated Display - APC", - }, - ) - mr.append( - "items", - { - "item_code": "Pocketful of Bay", - "delivery_date": mr.schedule_date, - "qty": 10, - "warehouse": "Refrigerated Display - APC", - }, - ) - mr.append( - "items", - { - "item_code": "Tower of Bay-bel", - "delivery_date": mr.schedule_date, - "qty": 20, - "warehouse": "Refrigerated Display - APC", - }, - ) - mr.save() - mr.submit() - mr = frappe.new_doc("Material Request") - mr.material_request_type = "Purchase" - mr.schedule_date = mr.transaction_date = settings.day - mr.title = "Boxes" - mr.company = settings.company - - -def create_production_plan(settings, prod_plan_from_doc): - pp = frappe.new_doc("Production Plan") - pp.posting_date = settings.day - pp.company = settings.company - pp.combine_sub_items = 1 - if prod_plan_from_doc == "Sales Order": - pp.get_items_from = "Sales Order" - pp.append( - "sales_orders", - { - "sales_order": frappe.get_last_doc("Sales Order").name, - }, - ) - pp.get_items() - else: - pp.get_items_from = "Material Request" - pp.append( - "material_requests", - { - "material_request": frappe.get_last_doc("Material Request").name, - }, - ) - pp.get_mr_items() - for item in pp.po_items: - item.planned_start_date = settings.day - pp.get_sub_assembly_items() - for item in pp.sub_assembly_items: - item.schedule_date = settings.day - if item.production_item == "Pie Crust": - idx = item.idx - item.type_of_manufacturing = "Subcontract" - item.supplier = "Credible Contract Baking" - item.qty = 50 - pp.append("sub_assembly_items", pp.sub_assembly_items[idx - 1].as_dict()) - pp.sub_assembly_items[-1].name = None - pp.sub_assembly_items[-1].type_of_manufacturing = "In House" - pp.sub_assembly_items[-1].bom_no = "BOM-Pie Crust-001" - pp.sub_assembly_items[-1].supplier = None - pp.for_warehouse = "Storeroom - APC" - raw_materials = get_items_for_material_requests( - pp.as_dict(), warehouses=None, get_parent_warehouse_data=None - ) - for row in raw_materials: - pp.append( - "mr_items", - { - **row, - "warehouse": frappe.get_value( - "Item Default", {"parent": row.get("item_code")}, "default_warehouse" - ), - }, - ) - pp.save() - pp.submit() - - pp.make_material_request() - mr = frappe.get_last_doc("Material Request") - mr.schedule_date = mr.transaction_date = settings.day - mr.company = settings.company - mr.save() - mr.submit() - - pp.make_work_order() - wos = frappe.get_all("Work Order", {"production_plan": pp.name}) - for wo in wos: - wo = frappe.get_doc("Work Order", wo) - wo.wip_warehouse = "Kitchen - APC" - wo.save() - wo.submit() - job_cards = frappe.get_all("Job Card", {"work_order": wo.name}) - for job_card in job_cards: - job_card = frappe.get_doc("Job Card", job_card) - job_card.time_logs[0].completed_qty = wo.qty - job_card.save() - job_card.submit() - - -def create_fruit_material_request(settings): - fruits = [ - "Bayberry", - "Cocoplum", - "Damson Plum", - "Gooseberry", - "Hairless Rambutan", - "Kaduka Lime", - "Limequat", - "Tayberry", - ] - - for fruit in fruits: - i = frappe.get_doc("Item", fruit) - i.append( - "item_defaults", - { - "company": "Chelsea Fruit Co", - "default_warehouse": "Stores - CFC", - "default_supplier": "Southern Fruit Supply", - }, - ) - i.save() - ip = frappe.copy_doc(frappe.get_doc("Item Price", {"item_code": fruit})) - ip.price_list = "Standard Buying" - ip.price_list_rate = flt(ip.price_list_rate * 0.75, 2) - ip.save() - - mr = frappe.new_doc("Material Request") - mr.company = "Chelsea Fruit Co" - mr.transaction_date = settings.day - mr.schedule_date = getdate() - mr.purpose = "Purchase" - for f in fruits: - mr.append( - "items", - { - "item_code": f, - "qty": 100, - "schedule_date": mr.schedule_date, - "warehouse": "Stores - CFC", - "uom": "Pound", - }, - ) - mr.save() - mr.submit() - - -def create_quotations(settings): - quotation = frappe.new_doc("Quotation") - - items = ["Ambrosia Pie", "Gooseberry Pie", "Double Plum Pie"] - for item in items: - i = frappe.get_doc("Item", item) - i.append( - "item_defaults", - { - "company": "Chelsea Fruit Co", - "default_warehouse": "Finished Goods - CFC", - }, - ) - i.save() - - values = { - "quotation_to": "Customer", - "order_type": "Sales", - "party_name": "Almacs Food Group", - "selling_price_list": "Bakery Wholesale", - "currency": "USD", - "conversion_rate": 1, - "transaction_date": nowdate(), - "valid_till": add_months(nowdate(), 1), - "items": [{"item_code": "Ambrosia Pie", "qty": 1}, {"item_code": "Gooseberry Pie", "qty": 5}], - "company": settings.company, - } - quotation.update(values) - quotation.save() - quotation.submit() - - quotation = frappe.new_doc("Quotation") - values = { - "quotation_to": "Customer", - "order_type": "Sales", - "party_name": "Almacs Food Group", - "selling_price_list": "Bakery Wholesale", - "currency": "USD", - "conversion_rate": 1, - "transaction_date": nowdate(), - "valid_till": add_months(nowdate(), 1), - "items": [{"item_code": "Ambrosia Pie", "qty": 1}, {"item_code": "Gooseberry Pie", "qty": 5}], - "company": settings.company, - } - quotation.update(values) - quotation.save() - quotation.submit() - - quotation = frappe.new_doc("Quotation") - values = { - "quotation_to": "Customer", - "order_type": "Sales", - "party_name": "Downtown Deli", - "selling_price_list": "Bakery Wholesale", - "currency": "USD", - "conversion_rate": 1, - "transaction_date": nowdate(), - "valid_till": add_months(nowdate(), 1), - "items": [{"item_code": "Ambrosia Pie", "qty": 2}, {"item_code": "Double Plum Pie", "qty": 1}], - "company": settings.company, - } - quotation.update(values) - quotation.save() - quotation.submit() - - quotation = frappe.new_doc("Quotation") - values = { - "quotation_to": "Customer", - "order_type": "Sales", - "party_name": "Almacs Food Group", - "selling_price_list": "Bakery Wholesale", - "currency": "USD", - "conversion_rate": 1, - "transaction_date": nowdate(), - "valid_till": add_months(nowdate(), 1), - "items": [{"item_code": "Ambrosia Pie", "qty": 5}, {"item_code": "Double Plum Pie", "qty": 10}], - "company": "Chelsea Fruit Co", - } - quotation.update(values) - quotation.save() - quotation.submit() - - -def create_specifications(settings=None): - for c in ( - ("Red", "#E24C4C"), - ("Blue", "#2490EF"), - ("Purple", "#8684FF"), - ("Green", "#8CCF54"), - ("Yellow", "#FFFF00"), - ("White", "#EEEEEE"), - ("Black", "#1111111"), - ): - if not frappe.db.exists("Color", c[0]): - color = frappe.new_doc("Color") - color.name = c[0] - color.color = c[1] - color.save() - - for spec in specifications: - if frappe.db.exists("Specification", spec.get("name")): - s = frappe.get_doc("Specification", spec.get("name")) - else: - s = frappe.new_doc("Specification") - s.name = spec.get("name") - s.dt = spec.get("dt") - s.apply_on = spec.get("apply_on") - s.enabled = spec.get("enabled") - for at in spec.get("attributes"): - s.append("attributes", at) - s.save() -======= # Copyright (c) 2024, AgriTheory and contributors # For license information, please see license.txt @@ -812,21 +6,25 @@ def create_specifications(settings=None): from itertools import groupby import frappe +from frappe.desk.page.setup_wizard.setup_wizard import setup_complete +from frappe.utils.data import add_months, flt, getdate, nowdate, get_datetime + from erpnext.accounts.doctype.account.account import update_account_number from erpnext.manufacturing.doctype.production_plan.production_plan import ( get_items_for_material_requests, ) from erpnext.setup.utils import enable_all_roles_and_domains, set_defaults_for_tests from erpnext.stock.get_item_details import get_item_details -from frappe.desk.page.setup_wizard.setup_wizard import setup_complete -from frappe.utils import add_months, nowdate -from frappe.utils.data import flt, getdate + +from webshop.webshop.doctype.website_item.website_item import make_website_item from inventory_tools.tests.fixtures import ( + attributes, boms, customers, items, operations, + specifications, suppliers, workstations, ) @@ -914,6 +112,7 @@ def create_test_data(): create_production_plan(settings, prod_plan_from_doc) create_fruit_material_request(settings) create_quotations(settings) + create_specifications(settings) def create_suppliers(settings): @@ -1049,6 +248,11 @@ def create_item_groups(settings): ig.parent_item_group = "All Item Groups" ig.save() + if not frappe.db.exists("Brand", "Ambrosia Pie Co"): + brand = frappe.new_doc("Brand") + brand.brand = "Ambrosia Pie Co" + brand.save() + def create_price_lists(settings): if not frappe.db.exists("Price List", "Bakery Buying"): @@ -1096,6 +300,8 @@ def create_items(settings): i.valuation_rate = item.get("valuation_rate") or 0 i.is_sub_contracted_item = item.get("is_sub_contracted_item") or 0 i.default_warehouse = settings.get("warehouse") + i.weight_uom = item.get("weight_uom", "Pound") if i.is_stock_item else None + i.weight_per_unit = item.get("weight_per_unit") i.default_material_request_type = ( "Purchase" if item.get("item_group") in ("Bakery Supplies", "Ingredients") @@ -1113,6 +319,9 @@ def create_items(settings): else 0 ) i.is_sales_item = 1 if item.get("item_group") == "Baked Goods" else 0 + i.sales_uom = "Nos" if i.is_sales_item else None + i.shelf_life_in_days = 7 if i.is_sales_item else None + i.brand = "Ambrosia Pie Co" if i.is_sales_item else None i.append( "item_defaults", { @@ -1157,6 +366,11 @@ def create_items(settings): ) se.save() se.submit() + if i.is_sales_item: + website_item = make_website_item(i, True) + website_item = frappe.get_doc("Website Item", website_item[0]) + website_item.route = f"products/{frappe.scrub(i.name)}" + website_item.save() def create_warehouses(settings): @@ -1427,11 +641,22 @@ def create_production_plan(settings, prod_plan_from_doc): wo.save() wo.submit() job_cards = frappe.get_all("Job Card", {"work_order": wo.name}) + start_time = get_datetime() for job_card in job_cards: job_card = frappe.get_doc("Job Card", job_card) - job_card.append("time_logs", {"completed_qty": wo.qty}) - job_card.save() - job_card.submit() + batch_size, total_operation_time = frappe.get_value( + "Operation", job_card.operation, ["batch_size", "total_operation_time"] + ) + time_in_mins = (total_operation_time / batch_size) * wo.qty + job_card.append( + "time_logs", + { + "completed_qty": wo.qty, + "from_time": start_time, + "to_time": start_time + datetime.timedelta(minutes=time_in_mins), + "time_in_mins": time_in_mins, + }, + ) def create_fruit_material_request(settings): @@ -1563,4 +788,33 @@ def create_quotations(settings): quotation.update(values) quotation.save() quotation.submit() ->>>>>>> 12d5afa2ce39627719b130a5ed0e5ce879c818f6 + + +def create_specifications(settings=None): + for c in ( + ("Red", "#E24C4C"), + ("Blue", "#2490EF"), + ("Purple", "#8684FF"), + ("Green", "#8CCF54"), + ("Yellow", "#FFFF00"), + ("White", "#EEEEEE"), + ("Black", "#1111111"), + ): + if not frappe.db.exists("Color", c[0]): + color = frappe.new_doc("Color") + color.name = c[0] + color.color = c[1] + color.save() + + for spec in specifications: + if frappe.db.exists("Specification", spec.get("name")): + s = frappe.get_doc("Specification", spec.get("name")) + else: + s = frappe.new_doc("Specification") + s.name = spec.get("name") + s.dt = spec.get("dt") + s.apply_on = spec.get("apply_on") + s.enabled = spec.get("enabled") + for at in spec.get("attributes"): + s.append("attributes", at) + s.save() diff --git a/inventory_tools/tests/test_alternative_workstation.py b/inventory_tools/tests/test_alternative_workstation.py index 2b43bf9..b0e7b39 100644 --- a/inventory_tools/tests/test_alternative_workstation.py +++ b/inventory_tools/tests/test_alternative_workstation.py @@ -1,37 +1,40 @@ -import frappe -import pytest - - -@pytest.mark.order(45) -def test_alternative_workstation_query(): - # test default settings - frappe.call( - "frappe.desk.search.search_link", - **{ - "doctype": "Workstation", - "txt": "", - "reference_doctype": "Job Card", - }, - ) - assert len(frappe.response.results) == 16 # all workstations - - # test with inventory tools settings - inventory_tools_settings = frappe.get_doc( - "Inventory Tools Settings", frappe.defaults.get_defaults().get("company") - ) - inventory_tools_settings.allow_alternative_workstations = True - inventory_tools_settings.save() - frappe.call( - "frappe.desk.search.search_link", - **{ - "doctype": "Workstation", - "txt": "", - "query": "inventory_tools.inventory_tools.overrides.workstation.get_alternative_workstations", - "filters": {"operation": "Gather Pie Filling Ingredients"}, - "reference_doctype": "Job Card", - }, - ) - assert len(frappe.response.results) == 2 - assert frappe.response.results[0].get("value") == "Food Prep Table 1" # default returns first - assert "Default" in frappe.response.results[0].get("description") - assert frappe.response.results[1].get("value") == "Food Prep Table 2" +# Copyright (c) 2024, AgriTheory and contributors +# For license information, please see license.txt + +import frappe +import pytest + + +@pytest.mark.order(45) +def test_alternative_workstation_query(): + # test default settings + frappe.call( + "frappe.desk.search.search_link", + **{ + "doctype": "Workstation", + "txt": "", + "reference_doctype": "Job Card", + }, + ) + assert len(frappe.response.results) == 16 # all workstations + + # test with inventory tools settings + inventory_tools_settings = frappe.get_doc( + "Inventory Tools Settings", frappe.defaults.get_defaults().get("company") + ) + inventory_tools_settings.allow_alternative_workstations = True + inventory_tools_settings.save() + frappe.call( + "frappe.desk.search.search_link", + **{ + "doctype": "Workstation", + "txt": "", + "query": "inventory_tools.inventory_tools.overrides.workstation.get_alternative_workstations", + "filters": {"operation": "Gather Pie Filling Ingredients"}, + "reference_doctype": "Job Card", + }, + ) + assert len(frappe.response.results) == 2 + assert frappe.response.results[0].get("value") == "Food Prep Table 1" # default returns first + assert "Default" in frappe.response.results[0].get("description") + assert frappe.response.results[1].get("value") == "Food Prep Table 2" diff --git a/inventory_tools/tests/test_faceted_search.py b/inventory_tools/tests/test_faceted_search.py index 9ad1a86..69a8436 100644 --- a/inventory_tools/tests/test_faceted_search.py +++ b/inventory_tools/tests/test_faceted_search.py @@ -1,108 +1,111 @@ -import frappe -import pytest - -# don't generate spec values in setup -# create overlapping spec (Item) - -# test generation of values for - -# spec_items = frappe.get_all("Item", {"item_group": "Baked Goods"}) -# for spec_item in spec_items: -# if spec_item.name not in attributes: -# continue -# spec_item = frappe.get_doc("Item", spec_item) -# s.create_linked_values(spec_item, attributes[spec_item.name]) - - -def test_values_updated_on_item_save(): - # assert spec value doesn't exist - frappe.flags.in_test = True - values = frappe.get_all( - "Specification Value", {"reference_doctype": "Item", "reference_name": "Double Plum Pie"} - ) - assert values == [] - doc = frappe.get_doc("Item", "Double Plum Pie") - doc.save() - values = frappe.get_all( - "Specification Value", {"reference_doctype": "Item", "reference_name": "Double Plum Pie"} - ) - assert len(values) == 4 - doc.weight_per_unit = 12 - doc.save() - values = frappe.get_all( - "Specification Value", - {"reference_doctype": "Item", "reference_name": "Double Plum Pie"}, - ) - assert len(values) == 4 - new_weight = frappe.get_all( - "Specification Value", - {"reference_doctype": "Item", "reference_name": "Double Plum Pie", "attribute": "Weight"}, - "value", - ) - assert len(new_weight) == 1 - assert int(new_weight[0].value) == 12 - doc.weight_per_unit = 8 - doc.save() - new_weight = frappe.get_all( - "Specification Value", - {"reference_doctype": "Item", "reference_name": "Double Plum Pie", "attribute": "Weight"}, - "value", - ) - assert len(new_weight) == 1 - assert int(new_weight[0].value) == 8 - values = frappe.get_all( - "Specification Value", {"reference_doctype": "Item", "reference_name": "Double Plum Pie"} - ) - assert len(values) == 4 - # cleanup - for value in values: - frappe.delete_doc("Specification Value", value.name, force=True) - - -def test_generate_values(): - frappe.flags.in_test = True - doc = frappe.get_doc("Specification", "Items") - assert len(doc.attributes) == 3 - frappe.call( - "inventory_tools.inventory_tools.doctype.specification.specification.create_specification_values", - **{ - "spec": doc.name, - "specifications": [ - { - "attribute": a.attribute_name, - "field": a.field, - } - for a in doc.attributes - ], - } - ) - assert ( - len(frappe.get_all("Specification Value", {"specification": doc.name})) == 36 * 2 - ) # total items x computed attributes - - -def test_generate_values_on_overlapping_items(): - frappe.flags.in_test = True - doc = frappe.get_doc("Specification", "Baked Goods") - assert len(doc.attributes) == 4 - frappe.call( - "inventory_tools.inventory_tools.doctype.specification.specification.create_specification_values", - **{ - "spec": doc.name, - "specifications": [ - { - "attribute": a.attribute_name, - "field": a.field, - } - for a in doc.attributes - ], - } - ) - assert ( - len(frappe.get_all("Specification Value", {"specification": doc.name})) == 6 * 2 - ) # total items x computed attributes - - -def test_delete_of_specification_value(): - frappe.flags.in_test = True - # via update_specification_values +# Copyright (c) 2024, AgriTheory and contributors +# For license information, please see license.txt + +import frappe +import pytest + +# don't generate spec values in setup +# create overlapping spec (Item) + +# test generation of values for + +# spec_items = frappe.get_all("Item", {"item_group": "Baked Goods"}) +# for spec_item in spec_items: +# if spec_item.name not in attributes: +# continue +# spec_item = frappe.get_doc("Item", spec_item) +# s.create_linked_values(spec_item, attributes[spec_item.name]) + + +def test_values_updated_on_item_save(): + # assert spec value doesn't exist + frappe.flags.in_test = True + values = frappe.get_all( + "Specification Value", {"reference_doctype": "Item", "reference_name": "Double Plum Pie"} + ) + assert values == [] + doc = frappe.get_doc("Item", "Double Plum Pie") + doc.save() + values = frappe.get_all( + "Specification Value", {"reference_doctype": "Item", "reference_name": "Double Plum Pie"} + ) + assert len(values) == 4 + doc.weight_per_unit = 12 + doc.save() + values = frappe.get_all( + "Specification Value", + {"reference_doctype": "Item", "reference_name": "Double Plum Pie"}, + ) + assert len(values) == 4 + new_weight = frappe.get_all( + "Specification Value", + {"reference_doctype": "Item", "reference_name": "Double Plum Pie", "attribute": "Weight"}, + "value", + ) + assert len(new_weight) == 1 + assert int(new_weight[0].value) == 12 + doc.weight_per_unit = 8 + doc.save() + new_weight = frappe.get_all( + "Specification Value", + {"reference_doctype": "Item", "reference_name": "Double Plum Pie", "attribute": "Weight"}, + "value", + ) + assert len(new_weight) == 1 + assert int(new_weight[0].value) == 8 + values = frappe.get_all( + "Specification Value", {"reference_doctype": "Item", "reference_name": "Double Plum Pie"} + ) + assert len(values) == 4 + # cleanup + for value in values: + frappe.delete_doc("Specification Value", value.name, force=True) + + +def test_generate_values(): + frappe.flags.in_test = True + doc = frappe.get_doc("Specification", "Items") + assert len(doc.attributes) == 3 + frappe.call( + "inventory_tools.inventory_tools.doctype.specification.specification.create_specification_values", + **{ + "spec": doc.name, + "specifications": [ + { + "attribute": a.attribute_name, + "field": a.field, + } + for a in doc.attributes + ], + } + ) + assert ( + len(frappe.get_all("Specification Value", {"specification": doc.name})) == 36 * 2 + ) # total items x computed attributes + + +def test_generate_values_on_overlapping_items(): + frappe.flags.in_test = True + doc = frappe.get_doc("Specification", "Baked Goods") + assert len(doc.attributes) == 4 + frappe.call( + "inventory_tools.inventory_tools.doctype.specification.specification.create_specification_values", + **{ + "spec": doc.name, + "specifications": [ + { + "attribute": a.attribute_name, + "field": a.field, + } + for a in doc.attributes + ], + } + ) + assert ( + len(frappe.get_all("Specification Value", {"specification": doc.name})) == 6 * 2 + ) # total items x computed attributes + + +def test_delete_of_specification_value(): + frappe.flags.in_test = True + # via update_specification_values diff --git a/package.json b/package.json index c30e27b..60a7fe6 100644 --- a/package.json +++ b/package.json @@ -1,25 +1,25 @@ -{ - "name": "inventory_tools", - "license": "MIT", - "scripts": { - "build": "vite build --config=./inventory_tools/public/js/vite.config.js", - "dev": "vite build --watch --config=./inventory_tools/public/js/vite.config.js" - }, - "dependencies": { - "@vueuse/core": "^10.9.0", - "vue": "^3.3.10" - }, - "devDependencies": { - "@vitejs/plugin-vue": "^4.0.0", - "frappe-ui": "^0.0.105", - "vite": "^4.0.2" - }, - "repository": { - "type": "git", - "url": "https://github.com/agritheory/inventory_tools.git" - }, - "publishConfig": { - "access": "restricted" - }, - "private": true -} +{ + "name": "inventory_tools", + "license": "MIT", + "scripts": { + "build": "vite build --config=./inventory_tools/public/js/vite.config.js", + "dev": "vite build --watch --config=./inventory_tools/public/js/vite.config.js" + }, + "dependencies": { + "@vueuse/core": "^10.9.0", + "vue": "^3.3.10" + }, + "devDependencies": { + "@vitejs/plugin-vue": "^4.0.0", + "frappe-ui": "^0.0.105", + "vite": "^4.0.2" + }, + "repository": { + "type": "git", + "url": "https://github.com/agritheory/inventory_tools.git" + }, + "publishConfig": { + "access": "restricted" + }, + "private": true +}