2026-05-18 14:47:20 +00:00
|
|
|
#!/usr/bin/env bash
|
|
|
|
|
set -euo pipefail
|
|
|
|
|
|
|
|
|
|
# Load .env.local secrets and run integration tests inside the app container.
|
|
|
|
|
if [ -f "$(dirname "$0")/../.env.local" ]; then
|
|
|
|
|
set -a
|
|
|
|
|
# shellcheck disable=SC1091
|
|
|
|
|
source "$(dirname "$0")/../.env.local"
|
|
|
|
|
set +a
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
docker compose exec \
|
|
|
|
|
-e FRAPPE_ERP_BASE_URL="${FRAPPE_ERP_BASE_URL:-}" \
|
|
|
|
|
-e FRAPPE_ERP_API_KEY="${FRAPPE_ERP_API_KEY:-}" \
|
|
|
|
|
-e FRAPPE_ERP_API_SECRET="${FRAPPE_ERP_API_SECRET:-}" \
|
feat: Frappe ERP matching, pipeline model cache, ACL, stock field, specs by type
Frappe ERP:
- findExistingCustomer() on FrappeErpAdapter — two-step name+address lookup
- FrappeHttpClient: add put() method; switch invoice submit to PUT docstatus=1 (Frappe v16)
- buildItemDescription() uses specsText + inventory number + serial number
- Integration tests: find Simon Kühn, create real 1337€ invoice, cancel+delete in tearDown
- FRAPPE_GENERIC_ITEM_CODE=SKU002 added to .env.local and bin/test-integration
Pipeline — model cache:
- PhotoUploadHandler: after vision, check DB for existing article with same modelNumber
- On match: copy ebayTitle/ebayDescription/specsText/attributes, skip specs+JSON+eBay steps
- DraftArticleHandler: apply model_match data and mark job complete directly
- ArticleRepository: findCompletedByModelNumber() query
Pipeline — specs by article type:
- SpecsResearchAgent: accept attributeFields list, format as bullet list in {{fields}} var
- SpecsResearchHandler: derive attribute names from ArticleType, pass to agent
- SpecsResearchMessage: add attributeFields param
- Prompt migration: replace hardcoded laptop spec list with {{fields}} placeholder
Article:
- specsText field (nullable text column + migration)
- stock field visible on index and editable in CRUD form
- addAttributeValue()/removeAttributeValue() adder-remover pair for Symfony form binding
- AttributeValue::getArticle() getter
- AttributeValueFormType: detect required attributes from ArticleType assignments, set required=true
- ManualIngestType: add stock/quantity field (default 1, min 1)
Users / ACL:
- PermissionVoter: define named permission constants + allPermissions()
- User: getGrantedPermissions()/setGrantedPermissions() helpers
- UserCrudController: permissions checkbox group on edit form
UI / assets:
- public/css/admin/custom.css: red asterisk for required fields
- DashboardController: register custom CSS
Infra:
- PipelineJobFailureListener: mark job failed (with real error) when Messenger exhausts retries
- doctrine.yaml: exclude app.inventory_seq from schema diff
- ErpAdapterInterface: add findExistingCustomer()
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 16:42:15 +00:00
|
|
|
-e FRAPPE_GENERIC_ITEM_CODE="${FRAPPE_GENERIC_ITEM_CODE:-}" \
|
2026-05-18 18:02:49 +00:00
|
|
|
-e EBAY_CLIENT_ID="${EBAY_CLIENT_ID:-}" \
|
|
|
|
|
-e EBAY_CLIENT_SECRET="${EBAY_CLIENT_SECRET:-}" \
|
|
|
|
|
-e EBAY_API_BASE_URL="${EBAY_API_BASE_URL:-}" \
|
|
|
|
|
-e EBAY_OAUTH_BASE_URL="${EBAY_OAUTH_BASE_URL:-}" \
|
|
|
|
|
-e EBAY_MARKETPLACE_ID="${EBAY_MARKETPLACE_ID:-EBAY_DE}" \
|
feat: Frappe ERP matching, pipeline model cache, ACL, stock field, specs by type
Frappe ERP:
- findExistingCustomer() on FrappeErpAdapter — two-step name+address lookup
- FrappeHttpClient: add put() method; switch invoice submit to PUT docstatus=1 (Frappe v16)
- buildItemDescription() uses specsText + inventory number + serial number
- Integration tests: find Simon Kühn, create real 1337€ invoice, cancel+delete in tearDown
- FRAPPE_GENERIC_ITEM_CODE=SKU002 added to .env.local and bin/test-integration
Pipeline — model cache:
- PhotoUploadHandler: after vision, check DB for existing article with same modelNumber
- On match: copy ebayTitle/ebayDescription/specsText/attributes, skip specs+JSON+eBay steps
- DraftArticleHandler: apply model_match data and mark job complete directly
- ArticleRepository: findCompletedByModelNumber() query
Pipeline — specs by article type:
- SpecsResearchAgent: accept attributeFields list, format as bullet list in {{fields}} var
- SpecsResearchHandler: derive attribute names from ArticleType, pass to agent
- SpecsResearchMessage: add attributeFields param
- Prompt migration: replace hardcoded laptop spec list with {{fields}} placeholder
Article:
- specsText field (nullable text column + migration)
- stock field visible on index and editable in CRUD form
- addAttributeValue()/removeAttributeValue() adder-remover pair for Symfony form binding
- AttributeValue::getArticle() getter
- AttributeValueFormType: detect required attributes from ArticleType assignments, set required=true
- ManualIngestType: add stock/quantity field (default 1, min 1)
Users / ACL:
- PermissionVoter: define named permission constants + allPermissions()
- User: getGrantedPermissions()/setGrantedPermissions() helpers
- UserCrudController: permissions checkbox group on edit form
UI / assets:
- public/css/admin/custom.css: red asterisk for required fields
- DashboardController: register custom CSS
Infra:
- PipelineJobFailureListener: mark job failed (with real error) when Messenger exhausts retries
- doctrine.yaml: exclude app.inventory_seq from schema diff
- ErpAdapterInterface: add findExistingCustomer()
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 16:42:15 +00:00
|
|
|
app php vendor/bin/phpunit --testdox "${@:-tests/Integration/}"
|