@tailor-platform/erp-kit 0.0.1 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +196 -28
- package/dist/cli.js +894 -0
- package/package.json +65 -8
- package/rules/app-compose/backend/auth.md +78 -0
- package/rules/app-compose/frontend/auth.md +55 -0
- package/rules/app-compose/frontend/component.md +55 -0
- package/rules/app-compose/frontend/page.md +86 -0
- package/rules/app-compose/frontend/screen-detailview.md +112 -0
- package/rules/app-compose/frontend/screen-form.md +145 -0
- package/rules/app-compose/frontend/screen-listview.md +159 -0
- package/rules/app-compose/structure.md +32 -0
- package/rules/module-development/commands.md +54 -0
- package/rules/module-development/cross-module-type-injection.md +28 -0
- package/rules/module-development/dependency-modules.md +24 -0
- package/rules/module-development/errors.md +12 -0
- package/rules/module-development/executors.md +67 -0
- package/rules/module-development/exports.md +13 -0
- package/rules/module-development/models.md +34 -0
- package/rules/module-development/structure.md +27 -0
- package/rules/module-development/sync-vs-async-operations.md +83 -0
- package/rules/module-development/testing.md +43 -0
- package/rules/sdk-best-practices/db-relations.md +74 -0
- package/rules/sdk-best-practices/sdk-docs.md +14 -0
- package/schemas/app-compose/actors.yml +34 -0
- package/schemas/app-compose/business-flow.yml +50 -0
- package/schemas/app-compose/requirements.yml +33 -0
- package/schemas/app-compose/resolver.yml +47 -0
- package/schemas/app-compose/screen.yml +81 -0
- package/schemas/app-compose/story.yml +67 -0
- package/schemas/module/command.yml +52 -0
- package/schemas/module/feature.yml +58 -0
- package/schemas/module/model.yml +70 -0
- package/schemas/module/module.yml +50 -0
- package/skills/1-module-docs/SKILL.md +107 -0
- package/skills/2-module-feature-breakdown/SKILL.md +66 -0
- package/skills/3-module-doc-review/SKILL.md +230 -0
- package/skills/4-module-tdd-implementation/SKILL.md +56 -0
- package/skills/5-module-implementation-review/SKILL.md +400 -0
- package/skills/app-compose-1-requirement-analysis/SKILL.md +85 -0
- package/skills/app-compose-2-requirements-breakdown/SKILL.md +88 -0
- package/skills/app-compose-3-doc-review/SKILL.md +112 -0
- package/skills/app-compose-4-design-mock/SKILL.md +248 -0
- package/skills/app-compose-5-design-mock-review/SKILL.md +283 -0
- package/skills/app-compose-6-implementation-spec/SKILL.md +122 -0
- package/skills/mock-scenario/SKILL.md +118 -0
- package/src/app.ts +1 -0
- package/src/cli.ts +120 -0
- package/src/commands/check.test.ts +30 -0
- package/src/commands/check.ts +66 -0
- package/src/commands/init.test.ts +77 -0
- package/src/commands/init.ts +87 -0
- package/src/commands/mock/index.ts +53 -0
- package/src/commands/mock/start.ts +179 -0
- package/src/commands/mock/validate.test.ts +185 -0
- package/src/commands/mock/validate.ts +198 -0
- package/src/commands/scaffold.test.ts +76 -0
- package/src/commands/scaffold.ts +119 -0
- package/src/commands/sync-check.test.ts +125 -0
- package/src/commands/sync-check.ts +182 -0
- package/src/integration.test.ts +63 -0
- package/src/mdschema.ts +48 -0
- package/src/mockServer.ts +55 -0
- package/src/module.ts +86 -0
- package/src/modules/accounting/.gitkeep +0 -0
- package/src/modules/coa-management/.gitkeep +0 -0
- package/src/modules/inventory/.gitkeep +0 -0
- package/src/modules/manufacturing/.gitkeep +0 -0
- package/src/modules/primitives/README.md +39 -0
- package/src/modules/primitives/command/activateCategory.test.ts +75 -0
- package/src/modules/primitives/command/activateCategory.ts +50 -0
- package/src/modules/primitives/command/activateCurrency.test.ts +70 -0
- package/src/modules/primitives/command/activateCurrency.ts +50 -0
- package/src/modules/primitives/command/activateUnit.test.ts +53 -0
- package/src/modules/primitives/command/activateUnit.ts +50 -0
- package/src/modules/primitives/command/convertAmount.test.ts +275 -0
- package/src/modules/primitives/command/convertAmount.ts +126 -0
- package/src/modules/primitives/command/convertQuantity.test.ts +219 -0
- package/src/modules/primitives/command/convertQuantity.ts +73 -0
- package/src/modules/primitives/command/createCategory.test.ts +126 -0
- package/src/modules/primitives/command/createCategory.ts +89 -0
- package/src/modules/primitives/command/createCurrency.test.ts +191 -0
- package/src/modules/primitives/command/createCurrency.ts +77 -0
- package/src/modules/primitives/command/createExchangeRate.test.ts +216 -0
- package/src/modules/primitives/command/createExchangeRate.ts +91 -0
- package/src/modules/primitives/command/createUnit.test.ts +214 -0
- package/src/modules/primitives/command/createUnit.ts +88 -0
- package/src/modules/primitives/command/deactivateCategory.test.ts +97 -0
- package/src/modules/primitives/command/deactivateCategory.ts +62 -0
- package/src/modules/primitives/command/deactivateCurrency.test.ts +85 -0
- package/src/modules/primitives/command/deactivateCurrency.ts +55 -0
- package/src/modules/primitives/command/deactivateUnit.test.ts +78 -0
- package/src/modules/primitives/command/deactivateUnit.ts +62 -0
- package/src/modules/primitives/command/setBaseCurrency.test.ts +98 -0
- package/src/modules/primitives/command/setBaseCurrency.ts +74 -0
- package/src/modules/primitives/command/setReferenceUnit.test.ts +108 -0
- package/src/modules/primitives/command/setReferenceUnit.ts +84 -0
- package/src/modules/primitives/db/currency.ts +30 -0
- package/src/modules/primitives/db/exchangeRate.ts +28 -0
- package/src/modules/primitives/db/unit.ts +32 -0
- package/src/modules/primitives/db/uomCategory.ts +32 -0
- package/src/modules/primitives/docs/commands/ActivateCategory.md +34 -0
- package/src/modules/primitives/docs/commands/ActivateCurrency.md +33 -0
- package/src/modules/primitives/docs/commands/ActivateUnit.md +34 -0
- package/src/modules/primitives/docs/commands/ConvertAmount.md +50 -0
- package/src/modules/primitives/docs/commands/ConvertQuantity.md +43 -0
- package/src/modules/primitives/docs/commands/CreateCategory.md +44 -0
- package/src/modules/primitives/docs/commands/CreateCurrency.md +47 -0
- package/src/modules/primitives/docs/commands/CreateExchangeRate.md +48 -0
- package/src/modules/primitives/docs/commands/CreateUnit.md +48 -0
- package/src/modules/primitives/docs/commands/DeactivateCategory.md +38 -0
- package/src/modules/primitives/docs/commands/DeactivateCurrency.md +38 -0
- package/src/modules/primitives/docs/commands/DeactivateUnit.md +38 -0
- package/src/modules/primitives/docs/commands/SetBaseCurrency.md +39 -0
- package/src/modules/primitives/docs/commands/SetReferenceUnit.md +43 -0
- package/src/modules/primitives/docs/features/currency-definitions.md +55 -0
- package/src/modules/primitives/docs/features/exchange-rates.md +61 -0
- package/src/modules/primitives/docs/features/unit-conversion.md +66 -0
- package/src/modules/primitives/docs/features/uom-categories.md +52 -0
- package/src/modules/primitives/docs/models/Currency.md +45 -0
- package/src/modules/primitives/docs/models/ExchangeRate.md +33 -0
- package/src/modules/primitives/docs/models/Unit.md +46 -0
- package/src/modules/primitives/docs/models/UoMCategory.md +44 -0
- package/src/modules/primitives/generated/kysely-tailordb.ts +95 -0
- package/src/modules/primitives/index.ts +40 -0
- package/src/modules/primitives/lib/errors.ts +138 -0
- package/src/modules/primitives/lib/types.ts +20 -0
- package/src/modules/primitives/module.ts +66 -0
- package/src/modules/primitives/permissions.ts +18 -0
- package/src/modules/primitives/tailor.config.ts +11 -0
- package/src/modules/primitives/testing/fixtures.ts +161 -0
- package/src/modules/product-management/.gitkeep +0 -0
- package/src/modules/purchase/.gitkeep +0 -0
- package/src/modules/sales/.gitkeep +0 -0
- package/src/modules/shared/createContext.test.ts +39 -0
- package/src/modules/shared/createContext.ts +15 -0
- package/src/modules/shared/defineCommand.test.ts +42 -0
- package/src/modules/shared/defineCommand.ts +19 -0
- package/src/modules/shared/definePermissions.test.ts +146 -0
- package/src/modules/shared/definePermissions.ts +94 -0
- package/src/modules/shared/entityTypes.ts +15 -0
- package/src/modules/shared/errors.ts +22 -0
- package/src/modules/shared/index.ts +1 -0
- package/src/modules/shared/internal.ts +13 -0
- package/src/modules/shared/requirePermission.test.ts +47 -0
- package/src/modules/shared/requirePermission.ts +8 -0
- package/src/modules/shared/types.ts +4 -0
- package/src/modules/supplier-management/.gitkeep +0 -0
- package/src/modules/supplier-portal/.gitkeep +0 -0
- package/src/modules/testing/index.ts +120 -0
- package/src/modules/user-management/README.md +38 -0
- package/src/modules/user-management/command/activateUser.test.ts +112 -0
- package/src/modules/user-management/command/activateUser.ts +67 -0
- package/src/modules/user-management/command/assignPermissionToRole.test.ts +119 -0
- package/src/modules/user-management/command/assignPermissionToRole.ts +87 -0
- package/src/modules/user-management/command/assignRoleToUser.test.ts +162 -0
- package/src/modules/user-management/command/assignRoleToUser.ts +93 -0
- package/src/modules/user-management/command/createPermission.test.ts +143 -0
- package/src/modules/user-management/command/createPermission.ts +66 -0
- package/src/modules/user-management/command/createRole.test.ts +115 -0
- package/src/modules/user-management/command/createRole.ts +52 -0
- package/src/modules/user-management/command/createUser.test.ts +198 -0
- package/src/modules/user-management/command/createUser.ts +85 -0
- package/src/modules/user-management/command/deactivateUser.test.ts +112 -0
- package/src/modules/user-management/command/deactivateUser.ts +67 -0
- package/src/modules/user-management/command/logAuditEvent.test.ts +179 -0
- package/src/modules/user-management/command/logAuditEvent.ts +59 -0
- package/src/modules/user-management/command/reactivateUser.test.ts +115 -0
- package/src/modules/user-management/command/reactivateUser.ts +67 -0
- package/src/modules/user-management/command/revokePermissionFromRole.test.ts +112 -0
- package/src/modules/user-management/command/revokePermissionFromRole.ts +81 -0
- package/src/modules/user-management/command/revokeRoleFromUser.test.ts +112 -0
- package/src/modules/user-management/command/revokeRoleFromUser.ts +81 -0
- package/src/modules/user-management/db/auditEvent.ts +47 -0
- package/src/modules/user-management/db/permission.ts +31 -0
- package/src/modules/user-management/db/role.ts +28 -0
- package/src/modules/user-management/db/rolePermission.ts +44 -0
- package/src/modules/user-management/db/user.ts +38 -0
- package/src/modules/user-management/db/userRole.ts +44 -0
- package/src/modules/user-management/docs/commands/ActivateUser.md +36 -0
- package/src/modules/user-management/docs/commands/AssignPermissionToRole.md +39 -0
- package/src/modules/user-management/docs/commands/AssignRoleToUser.md +43 -0
- package/src/modules/user-management/docs/commands/CreatePermission.md +35 -0
- package/src/modules/user-management/docs/commands/CreateRole.md +35 -0
- package/src/modules/user-management/docs/commands/CreateUser.md +41 -0
- package/src/modules/user-management/docs/commands/DeactivateUser.md +38 -0
- package/src/modules/user-management/docs/commands/LogAuditEvent.md +37 -0
- package/src/modules/user-management/docs/commands/ReactivateUser.md +37 -0
- package/src/modules/user-management/docs/commands/RevokePermissionFromRole.md +40 -0
- package/src/modules/user-management/docs/commands/RevokeRoleFromUser.md +40 -0
- package/src/modules/user-management/docs/features/audit-trail.md +80 -0
- package/src/modules/user-management/docs/features/role-based-access-control.md +76 -0
- package/src/modules/user-management/docs/features/user-account-management.md +64 -0
- package/src/modules/user-management/docs/models/AuditEvent.md +34 -0
- package/src/modules/user-management/docs/models/Permission.md +31 -0
- package/src/modules/user-management/docs/models/Role.md +31 -0
- package/src/modules/user-management/docs/models/RolePermission.md +33 -0
- package/src/modules/user-management/docs/models/User.md +47 -0
- package/src/modules/user-management/docs/models/UserRole.md +34 -0
- package/src/modules/user-management/docs/plans/2026-01-30-flattened-permissions-design.md +52 -0
- package/src/modules/user-management/executor/recomputeOnRolePermissionChange.ts +61 -0
- package/src/modules/user-management/generated/enums.ts +24 -0
- package/src/modules/user-management/generated/kysely-tailordb.ts +112 -0
- package/src/modules/user-management/index.ts +32 -0
- package/src/modules/user-management/lib/errors.ts +81 -0
- package/src/modules/user-management/lib/recomputeUserPermissions.ts +53 -0
- package/src/modules/user-management/lib/types.ts +31 -0
- package/src/modules/user-management/module.ts +77 -0
- package/src/modules/user-management/permissions.ts +15 -0
- package/src/modules/user-management/tailor.config.ts +11 -0
- package/src/modules/user-management/testing/fixtures.ts +98 -0
- package/src/schemas.ts +25 -0
- package/src/testing.ts +10 -0
- package/src/util.ts +3 -0
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# ConvertAmount
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
ConvertAmount transforms a monetary amount from one currency to another using the applicable exchange rate for a given date. The function looks up the most recent exchange rate on or before the specified date and applies it to calculate the converted amount. The result is rounded according to the target currency's decimal precision.
|
|
6
|
+
|
|
7
|
+
This function supports multi-currency operations including transaction recording, financial reporting, and consolidation.
|
|
8
|
+
|
|
9
|
+
## Business Rules
|
|
10
|
+
|
|
11
|
+
- Source and target currencies must both be active
|
|
12
|
+
- Exchange rate lookup uses the most recent rate with effectiveDate <= conversionDate
|
|
13
|
+
- Calculation: `result = amount x exchangeRate`
|
|
14
|
+
- Result is rounded to the target currency's `decimalPlaces`
|
|
15
|
+
- Same currency conversion (e.g., USD to USD) returns the original amount with rate of 1.0
|
|
16
|
+
- If no direct rate exists, inverse rate may be calculated: `1 / reverseRate`
|
|
17
|
+
- Amount must be non-negative (zero is allowed)
|
|
18
|
+
- Forward rates are supported: if conversion date is in the future and a forward rate exists, it will be used
|
|
19
|
+
|
|
20
|
+
## Process Flow
|
|
21
|
+
|
|
22
|
+
```mermaid
|
|
23
|
+
flowchart TD
|
|
24
|
+
A[Receive conversion request] --> B{Same currency?}
|
|
25
|
+
B -->|Yes| C[Return original amount]
|
|
26
|
+
B -->|No| D{Both currencies active?}
|
|
27
|
+
D -->|No| E[Return error: inactive currency]
|
|
28
|
+
D -->|Yes| F[Find rate for date]
|
|
29
|
+
F --> G{Direct rate found?}
|
|
30
|
+
G -->|Yes| H[Use direct rate]
|
|
31
|
+
G -->|No| I{Inverse rate found?}
|
|
32
|
+
I -->|Yes| J[Calculate inverse: 1/rate]
|
|
33
|
+
I -->|No| K[Return error: no rate available]
|
|
34
|
+
J --> H
|
|
35
|
+
H --> L[Calculate: amount x rate]
|
|
36
|
+
L --> M[Round to target decimal places]
|
|
37
|
+
M --> N[Return converted amount]
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## External Dependencies
|
|
41
|
+
|
|
42
|
+
- None
|
|
43
|
+
|
|
44
|
+
## Error Scenarios
|
|
45
|
+
|
|
46
|
+
- **Inactive currency**: Either source or target currency is inactive - return error identifying the inactive currency
|
|
47
|
+
- **No exchange rate**: No rate found for the currency pair on or before the specified date - return error with date and currency pair
|
|
48
|
+
- **Invalid amount**: Negative amount provided - return validation error
|
|
49
|
+
- **Currency not found**: Specified currency code/ID does not exist - return not found error
|
|
50
|
+
- **Date in future**: Conversion date is in the future and no forward rate exists - return error or use most recent rate based on configuration
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# ConvertQuantity
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
ConvertQuantity transforms a quantity from one unit of measure to another within the same category. The conversion uses the category's reference unit as an intermediary, calculating: `result = quantity x sourceConversionFactor / targetConversionFactor`. The result is rounded according to the target unit's precision setting.
|
|
6
|
+
|
|
7
|
+
This function supports core ERP operations where quantities must be expressed in different units for purchasing, inventory, and sales.
|
|
8
|
+
|
|
9
|
+
## Business Rules
|
|
10
|
+
|
|
11
|
+
- Source and target units must belong to the same UoMCategory
|
|
12
|
+
- Quantity must be a non-negative number (zero is allowed)
|
|
13
|
+
- Conversion factor calculation: `result = quantity x (sourceUnit.conversionFactor / targetUnit.conversionFactor)`
|
|
14
|
+
- Result is rounded to the target unit's `roundingPrecision` decimal places
|
|
15
|
+
- Converting between the same unit returns the original quantity
|
|
16
|
+
- Both units must be active
|
|
17
|
+
|
|
18
|
+
## Process Flow
|
|
19
|
+
|
|
20
|
+
```mermaid
|
|
21
|
+
flowchart TD
|
|
22
|
+
A[Receive conversion request] --> B{Same category?}
|
|
23
|
+
B -->|No| C[Return error: incompatible units]
|
|
24
|
+
B -->|Yes| D{Both units active?}
|
|
25
|
+
D -->|No| E[Return error: inactive unit]
|
|
26
|
+
D -->|Yes| F[Get source unit factor]
|
|
27
|
+
F --> G[Get target unit factor]
|
|
28
|
+
G --> H[Calculate: qty x sourceFactor / targetFactor]
|
|
29
|
+
H --> I[Apply target unit rounding precision]
|
|
30
|
+
I --> J[Return converted quantity]
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## External Dependencies
|
|
34
|
+
|
|
35
|
+
- None
|
|
36
|
+
|
|
37
|
+
## Error Scenarios
|
|
38
|
+
|
|
39
|
+
- **Incompatible units**: Source and target units belong to different categories - return error with message indicating the mismatch
|
|
40
|
+
- **Inactive unit**: Either source or target unit is inactive - return error identifying the inactive unit
|
|
41
|
+
- **Invalid quantity**: Negative quantity provided - return validation error (or allow based on configuration)
|
|
42
|
+
- **Unit not found**: Specified unit ID does not exist - return not found error
|
|
43
|
+
- **Overflow**: Calculation produces a number exceeding system limits - return overflow error
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# CreateCategory
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
CreateCategory establishes a new unit of measure category that groups related units where conversions are meaningful. Each category must have a designated reference unit that serves as the base for all conversion calculations within that category. The reference unit is created simultaneously with the category and has a conversion factor of 1.0.
|
|
6
|
+
|
|
7
|
+
This command supports initial system setup with standard categories (Unit, Weight, Volume, Length, Time) and business-specific category creation.
|
|
8
|
+
|
|
9
|
+
## Business Rules
|
|
10
|
+
|
|
11
|
+
- Category name must be unique across all categories (active and inactive)
|
|
12
|
+
- Category name is required and must be non-empty
|
|
13
|
+
- Reference unit must be specified at category creation time
|
|
14
|
+
- Reference unit is created with conversion factor of 1.0
|
|
15
|
+
- New categories are created in Active status by default
|
|
16
|
+
- Category cannot exist without at least one unit (the reference unit)
|
|
17
|
+
|
|
18
|
+
## Process Flow
|
|
19
|
+
|
|
20
|
+
```mermaid
|
|
21
|
+
flowchart TD
|
|
22
|
+
A[Receive create category request] --> B{Category name provided?}
|
|
23
|
+
B -->|No| C[Return error: missing name]
|
|
24
|
+
B -->|Yes| D{Category name unique?}
|
|
25
|
+
D -->|No| E[Return error: duplicate name]
|
|
26
|
+
D -->|Yes| F{Reference unit specified?}
|
|
27
|
+
F -->|No| G[Return error: missing reference unit]
|
|
28
|
+
F -->|Yes| H[Create category record]
|
|
29
|
+
H --> I[Create reference unit with factor 1.0]
|
|
30
|
+
I --> J[Link reference unit to category]
|
|
31
|
+
J --> K[Set category status: Active]
|
|
32
|
+
K --> L[Return created category with reference unit]
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## External Dependencies
|
|
36
|
+
|
|
37
|
+
- None
|
|
38
|
+
|
|
39
|
+
## Error Scenarios
|
|
40
|
+
|
|
41
|
+
- **Missing category name**: Name not provided - return validation error
|
|
42
|
+
- **Duplicate category name**: Category with same name already exists - return conflict error
|
|
43
|
+
- **Missing reference unit**: No reference unit details provided - return validation error indicating reference unit is required
|
|
44
|
+
- **Invalid reference unit**: Reference unit details are incomplete or invalid - return validation error with specific issues
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# CreateCurrency
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
CreateCurrency establishes a new monetary unit in the system with its ISO 4217 code, display symbol, name, and decimal precision. The first currency created automatically becomes the organization's base currency. Subsequent currencies are added as available currencies for multi-currency operations.
|
|
6
|
+
|
|
7
|
+
This command supports initial system setup and market expansion scenarios where new trading currencies are needed.
|
|
8
|
+
|
|
9
|
+
## Business Rules
|
|
10
|
+
|
|
11
|
+
- ISO 4217 code must be exactly 3 uppercase letters
|
|
12
|
+
- ISO 4217 code must be unique across all currencies (active and inactive)
|
|
13
|
+
- Currency symbol is required and typically 1-3 characters
|
|
14
|
+
- Decimal places must be a non-negative integer (0-4 typical range)
|
|
15
|
+
- First currency created automatically becomes the base currency with `isBaseCurrency: true`
|
|
16
|
+
- Subsequent currencies are created with `isBaseCurrency: false`
|
|
17
|
+
- New currencies are created in Active status by default
|
|
18
|
+
|
|
19
|
+
## Process Flow
|
|
20
|
+
|
|
21
|
+
```mermaid
|
|
22
|
+
flowchart TD
|
|
23
|
+
A[Receive create request] --> B{Validate ISO code format}
|
|
24
|
+
B -->|Invalid| C[Return error: invalid ISO code]
|
|
25
|
+
B -->|Valid| D{ISO code unique?}
|
|
26
|
+
D -->|No| E[Return error: duplicate code]
|
|
27
|
+
D -->|Yes| F{Validate decimal places}
|
|
28
|
+
F -->|Invalid| G[Return error: invalid decimal places]
|
|
29
|
+
F -->|Valid| H{Is first currency?}
|
|
30
|
+
H -->|Yes| I[Set as base currency]
|
|
31
|
+
H -->|No| J[Set isBaseCurrency: false]
|
|
32
|
+
I --> K[Create currency record]
|
|
33
|
+
J --> K
|
|
34
|
+
K --> L[Set status: Active]
|
|
35
|
+
L --> M[Return created currency]
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## External Dependencies
|
|
39
|
+
|
|
40
|
+
- None
|
|
41
|
+
|
|
42
|
+
## Error Scenarios
|
|
43
|
+
|
|
44
|
+
- **Invalid ISO code format**: Code is not exactly 3 uppercase letters - return validation error with format requirements
|
|
45
|
+
- **Duplicate ISO code**: Currency with same code already exists - return conflict error with existing currency reference
|
|
46
|
+
- **Invalid decimal places**: Value is negative or exceeds maximum (typically 4) - return validation error with valid range
|
|
47
|
+
- **Missing required fields**: Symbol or name not provided - return validation error listing missing fields
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# CreateExchangeRate
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
CreateExchangeRate establishes a new conversion ratio between a currency pair with a specific effective date. The rate specifies how many units of the target currency equal one unit of the source currency. Rates are date-based to support historical accuracy - transactions use the rate effective on their transaction date.
|
|
6
|
+
|
|
7
|
+
This command supports daily rate updates, period-end rate recording, and forward rate entry for future-dated transactions.
|
|
8
|
+
|
|
9
|
+
## Business Rules
|
|
10
|
+
|
|
11
|
+
- Source and target currencies must both exist and be active
|
|
12
|
+
- Source and target currencies must be different (no self-conversion rates)
|
|
13
|
+
- Rate value must be a positive decimal number (greater than zero)
|
|
14
|
+
- Effective date is required and determines when the rate becomes applicable
|
|
15
|
+
- Future effective dates are allowed (forward rates)
|
|
16
|
+
- Multiple rates for the same currency pair with different effective dates are allowed
|
|
17
|
+
- When a rate for the same currency pair and effective date already exists, the new rate supersedes (append-only semantics)
|
|
18
|
+
- Rate lookup uses the most recent rate with effectiveDate <= transaction date
|
|
19
|
+
|
|
20
|
+
## Process Flow
|
|
21
|
+
|
|
22
|
+
```mermaid
|
|
23
|
+
flowchart TD
|
|
24
|
+
A[Receive create rate request] --> B{Source currency exists and active?}
|
|
25
|
+
B -->|No| C[Return error: invalid source currency]
|
|
26
|
+
B -->|Yes| D{Target currency exists and active?}
|
|
27
|
+
D -->|No| E[Return error: invalid target currency]
|
|
28
|
+
D -->|Yes| F{Source != Target?}
|
|
29
|
+
F -->|No| G[Return error: same currency pair]
|
|
30
|
+
F -->|Yes| H{Rate value > 0?}
|
|
31
|
+
H -->|No| I[Return error: invalid rate value]
|
|
32
|
+
H -->|Yes| J{Effective date provided?}
|
|
33
|
+
J -->|No| K[Return error: missing effective date]
|
|
34
|
+
J -->|Yes| L[Create exchange rate record]
|
|
35
|
+
L --> M[Return created rate]
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## External Dependencies
|
|
39
|
+
|
|
40
|
+
- None
|
|
41
|
+
|
|
42
|
+
## Error Scenarios
|
|
43
|
+
|
|
44
|
+
- **Invalid source currency**: Source currency does not exist or is inactive - return error identifying the currency
|
|
45
|
+
- **Invalid target currency**: Target currency does not exist or is inactive - return error identifying the currency
|
|
46
|
+
- **Same currency pair**: Source and target currencies are the same - return error indicating self-conversion is not allowed
|
|
47
|
+
- **Invalid rate value**: Rate is zero, negative, or not a valid number - return validation error with acceptable range
|
|
48
|
+
- **Missing effective date**: No effective date provided - return validation error indicating date is required
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# CreateUnit
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
CreateUnit adds a new unit of measure to an existing category with its symbol, display name, and conversion factor relative to the category's reference unit. The conversion factor defines how many reference units equal one of this unit.
|
|
6
|
+
|
|
7
|
+
This command supports adding industry-specific units (like "Pallet" or "Roll"), regional units (metric and imperial), and precision units for specialized tracking.
|
|
8
|
+
|
|
9
|
+
## Business Rules
|
|
10
|
+
|
|
11
|
+
- Target category must exist and be active
|
|
12
|
+
- Unit symbol must be unique within the category
|
|
13
|
+
- Unit symbol is required and typically 1-5 characters
|
|
14
|
+
- Conversion factor must be a positive decimal number (greater than zero)
|
|
15
|
+
- Rounding precision must be a non-negative integer
|
|
16
|
+
- New units are created as non-reference units (only one reference unit per category)
|
|
17
|
+
- The conversion formula is: `quantity_in_reference = quantity_in_this_unit × conversion_factor`
|
|
18
|
+
|
|
19
|
+
## Process Flow
|
|
20
|
+
|
|
21
|
+
```mermaid
|
|
22
|
+
flowchart TD
|
|
23
|
+
A[Receive create unit request] --> B{Category exists and active?}
|
|
24
|
+
B -->|No| C[Return error: invalid category]
|
|
25
|
+
B -->|Yes| D{Symbol provided?}
|
|
26
|
+
D -->|No| E[Return error: missing symbol]
|
|
27
|
+
D -->|Yes| F{Symbol unique in category?}
|
|
28
|
+
F -->|No| G[Return error: duplicate symbol]
|
|
29
|
+
F -->|Yes| H{Conversion factor > 0?}
|
|
30
|
+
H -->|No| I[Return error: invalid conversion factor]
|
|
31
|
+
H -->|Yes| J{Rounding precision valid?}
|
|
32
|
+
J -->|No| K[Return error: invalid rounding precision]
|
|
33
|
+
J -->|Yes| L[Create unit record]
|
|
34
|
+
L --> M[Link unit to category]
|
|
35
|
+
M --> N[Return created unit]
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## External Dependencies
|
|
39
|
+
|
|
40
|
+
- None
|
|
41
|
+
|
|
42
|
+
## Error Scenarios
|
|
43
|
+
|
|
44
|
+
- **Invalid category**: Category does not exist or is inactive - return error identifying the category
|
|
45
|
+
- **Missing symbol**: Unit symbol not provided - return validation error
|
|
46
|
+
- **Duplicate symbol**: Unit with same symbol already exists in category - return conflict error
|
|
47
|
+
- **Invalid conversion factor**: Factor is zero, negative, or not a valid number - return validation error
|
|
48
|
+
- **Invalid rounding precision**: Precision is negative - return validation error with acceptable range
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# DeactivateCategory
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
DeactivateCategory disables a UoM category from being used in new product assignments while preserving all historical data and existing product associations. This command supports scenarios such as discontinuing a measurement standard or consolidating categories.
|
|
6
|
+
|
|
7
|
+
## Business Rules
|
|
8
|
+
|
|
9
|
+
- Target category must exist in the system
|
|
10
|
+
- Target category must be in Active status
|
|
11
|
+
- Category with active units cannot be deactivated - all units must be deactivated first
|
|
12
|
+
- Deactivating an already inactive category returns success with no state change
|
|
13
|
+
- Historical transactions and products using this category's units are not affected
|
|
14
|
+
- Deactivation prevents new products from being assigned units in this category
|
|
15
|
+
|
|
16
|
+
## Process Flow
|
|
17
|
+
|
|
18
|
+
```mermaid
|
|
19
|
+
flowchart TD
|
|
20
|
+
A[Receive deactivate request] --> B{Category exists?}
|
|
21
|
+
B -->|No| C[Return error: not found]
|
|
22
|
+
B -->|Yes| D{Has active units?}
|
|
23
|
+
D -->|Yes| E[Return error: has active units]
|
|
24
|
+
D -->|No| F{Current status?}
|
|
25
|
+
F -->|Inactive| G[Return success: already inactive]
|
|
26
|
+
F -->|Active| H[Update status to Inactive]
|
|
27
|
+
H --> I[Return deactivated category]
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## External Dependencies
|
|
31
|
+
|
|
32
|
+
- None
|
|
33
|
+
|
|
34
|
+
## Error Scenarios
|
|
35
|
+
|
|
36
|
+
- **Category not found**: Specified category ID does not exist - return not found error
|
|
37
|
+
- **Has active units**: Category still contains active units - return error listing active units that must be deactivated first
|
|
38
|
+
- **Invalid category ID**: Malformed or empty ID provided - return validation error
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# DeactivateCurrency
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
DeactivateCurrency disables a currency from being used in new transactions while preserving all historical data. This command supports scenarios such as market exit or currency obsolescence (e.g., legacy national currencies replaced by EUR). Deactivated currencies remain in the system for reporting and audit purposes.
|
|
6
|
+
|
|
7
|
+
## Business Rules
|
|
8
|
+
|
|
9
|
+
- Target currency must exist in the system
|
|
10
|
+
- Target currency must be in Active status
|
|
11
|
+
- Base currency cannot be deactivated - must first change base currency to another active currency
|
|
12
|
+
- Deactivating an already inactive currency returns success with no state change
|
|
13
|
+
- Historical transactions using this currency are not affected
|
|
14
|
+
- Deactivation prevents the currency from being used in new transactions, exchange rates, or price lists
|
|
15
|
+
|
|
16
|
+
## Process Flow
|
|
17
|
+
|
|
18
|
+
```mermaid
|
|
19
|
+
flowchart TD
|
|
20
|
+
A[Receive deactivate request] --> B{Currency exists?}
|
|
21
|
+
B -->|No| C[Return error: not found]
|
|
22
|
+
B -->|Yes| D{Is base currency?}
|
|
23
|
+
D -->|Yes| E[Return error: cannot deactivate base currency]
|
|
24
|
+
D -->|No| F{Current status?}
|
|
25
|
+
F -->|Inactive| G[Return success: already inactive]
|
|
26
|
+
F -->|Active| H[Update status to Inactive]
|
|
27
|
+
H --> I[Return deactivated currency]
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## External Dependencies
|
|
31
|
+
|
|
32
|
+
- None
|
|
33
|
+
|
|
34
|
+
## Error Scenarios
|
|
35
|
+
|
|
36
|
+
- **Currency not found**: Specified currency ID does not exist - return not found error
|
|
37
|
+
- **Base currency protection**: Attempting to deactivate the base currency - return error indicating base currency must be changed first
|
|
38
|
+
- **Invalid currency ID**: Malformed or empty ID provided - return validation error
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# DeactivateUnit
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
DeactivateUnit disables a unit of measure from being used in new product assignments and quantity conversions while preserving all historical data. This command supports scenarios such as discontinuing a measurement unit or consolidating units within a category.
|
|
6
|
+
|
|
7
|
+
## Business Rules
|
|
8
|
+
|
|
9
|
+
- Target unit must exist in the system
|
|
10
|
+
- Target unit must be in Active status
|
|
11
|
+
- Reference unit cannot be deactivated - must first change reference unit to another active unit in the category
|
|
12
|
+
- Deactivating an already inactive unit returns success with no state change
|
|
13
|
+
- Historical transactions and products using this unit are not affected
|
|
14
|
+
- Deactivation prevents the unit from being used in new product assignments or conversions
|
|
15
|
+
|
|
16
|
+
## Process Flow
|
|
17
|
+
|
|
18
|
+
```mermaid
|
|
19
|
+
flowchart TD
|
|
20
|
+
A[Receive deactivate request] --> B{Unit exists?}
|
|
21
|
+
B -->|No| C[Return error: not found]
|
|
22
|
+
B -->|Yes| D{Is reference unit?}
|
|
23
|
+
D -->|Yes| E[Return error: cannot deactivate reference unit]
|
|
24
|
+
D -->|No| F{Current status?}
|
|
25
|
+
F -->|Inactive| G[Return success: already inactive]
|
|
26
|
+
F -->|Active| H[Update status to Inactive]
|
|
27
|
+
H --> I[Return deactivated unit]
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## External Dependencies
|
|
31
|
+
|
|
32
|
+
- None
|
|
33
|
+
|
|
34
|
+
## Error Scenarios
|
|
35
|
+
|
|
36
|
+
- **Unit not found**: Specified unit ID does not exist - return not found error
|
|
37
|
+
- **Reference unit protection**: Attempting to deactivate the category's reference unit - return error indicating reference unit must be changed first
|
|
38
|
+
- **Invalid unit ID**: Malformed or empty ID provided - return validation error
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# SetBaseCurrency
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
SetBaseCurrency changes the organization's base currency to a different active currency. The base currency serves as the default for financial reporting, consolidation, and serves as the reference point for exchange rate conversions. This command supports scenarios such as corporate restructuring or relocating headquarters to a different country.
|
|
6
|
+
|
|
7
|
+
## Business Rules
|
|
8
|
+
|
|
9
|
+
- Target currency must exist in the system
|
|
10
|
+
- Target currency must be in Active status
|
|
11
|
+
- Only one currency can be base currency at a time
|
|
12
|
+
- Setting the current base currency as base returns success with no change
|
|
13
|
+
- Previous base currency remains active but loses base currency designation
|
|
14
|
+
- Exchange rates may need to be recalculated or new rates added after changing base currency
|
|
15
|
+
|
|
16
|
+
## Process Flow
|
|
17
|
+
|
|
18
|
+
```mermaid
|
|
19
|
+
flowchart TD
|
|
20
|
+
A[Receive set base request] --> B{Currency exists?}
|
|
21
|
+
B -->|No| C[Return error: not found]
|
|
22
|
+
B -->|Yes| D{Currency active?}
|
|
23
|
+
D -->|No| E[Return error: cannot set inactive currency as base]
|
|
24
|
+
D -->|Yes| F{Already base currency?}
|
|
25
|
+
F -->|Yes| G[Return success: no change needed]
|
|
26
|
+
F -->|No| H[Remove base flag from current base]
|
|
27
|
+
H --> I[Set base flag on target currency]
|
|
28
|
+
I --> J[Return updated currency]
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## External Dependencies
|
|
32
|
+
|
|
33
|
+
- None
|
|
34
|
+
|
|
35
|
+
## Error Scenarios
|
|
36
|
+
|
|
37
|
+
- **Currency not found**: Specified currency ID does not exist - return not found error
|
|
38
|
+
- **Inactive currency**: Target currency is not in Active status - return error indicating currency must be activated first
|
|
39
|
+
- **Invalid currency ID**: Malformed or empty ID provided - return validation error
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# SetReferenceUnit
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
SetReferenceUnit changes the reference unit for a UoM category to a different unit within the same category. When the reference unit changes, all conversion factors in the category are automatically recalculated relative to the new reference. The new reference unit's conversion factor becomes 1.0.
|
|
6
|
+
|
|
7
|
+
This command supports scenarios where business requirements change and a different unit becomes the standard for measurement.
|
|
8
|
+
|
|
9
|
+
## Business Rules
|
|
10
|
+
|
|
11
|
+
- Target unit must exist and belong to the specified category
|
|
12
|
+
- Target unit must be in the same category as the current reference unit
|
|
13
|
+
- Setting the current reference unit as reference returns success with no change
|
|
14
|
+
- When reference unit changes, the new reference unit's conversion factor becomes 1.0
|
|
15
|
+
- All other units' conversion factors are recalculated: `new_factor = old_factor / new_reference_old_factor`
|
|
16
|
+
- Historical conversion calculations are not affected (they used the factors at time of calculation)
|
|
17
|
+
|
|
18
|
+
## Process Flow
|
|
19
|
+
|
|
20
|
+
```mermaid
|
|
21
|
+
flowchart TD
|
|
22
|
+
A[Receive set reference request] --> B{Unit exists?}
|
|
23
|
+
B -->|No| C[Return error: unit not found]
|
|
24
|
+
B -->|Yes| D{Unit in specified category?}
|
|
25
|
+
D -->|No| E[Return error: unit not in category]
|
|
26
|
+
D -->|Yes| F{Already reference unit?}
|
|
27
|
+
F -->|Yes| G[Return success: no change needed]
|
|
28
|
+
F -->|No| H[Get new unit's current factor]
|
|
29
|
+
H --> I[Recalculate all unit factors]
|
|
30
|
+
I --> J[Set new unit factor to 1.0]
|
|
31
|
+
J --> K[Update category reference unit pointer]
|
|
32
|
+
K --> L[Return updated category]
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## External Dependencies
|
|
36
|
+
|
|
37
|
+
- None
|
|
38
|
+
|
|
39
|
+
## Error Scenarios
|
|
40
|
+
|
|
41
|
+
- **Unit not found**: Specified unit ID does not exist - return not found error
|
|
42
|
+
- **Unit not in category**: Unit belongs to a different category than specified - return error with category mismatch details
|
|
43
|
+
- **Invalid unit ID**: Malformed or empty ID provided - return validation error
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# Currency Definitions
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
Currency Definitions establish the monetary units available for use across the ERP system. Each currency record contains the ISO 4217 code, display symbol, name, and decimal precision. One currency is designated as the base currency for the organization, serving as the default for reporting and consolidation.
|
|
6
|
+
|
|
7
|
+
This feature provides the foundation for all multi-currency operations in sales, purchasing, and accounting.
|
|
8
|
+
|
|
9
|
+
## Business Purpose
|
|
10
|
+
|
|
11
|
+
Organizations operating internationally need to:
|
|
12
|
+
|
|
13
|
+
- Record transactions in the customer's or vendor's preferred currency
|
|
14
|
+
- Convert amounts to a consistent base currency for financial reporting
|
|
15
|
+
- Display currency symbols and format amounts correctly by locale
|
|
16
|
+
- Handle currencies with different decimal precisions (e.g., JPY has 0 decimals, USD has 2)
|
|
17
|
+
|
|
18
|
+
Currency definitions ensure consistent monetary handling across all business operations.
|
|
19
|
+
|
|
20
|
+
## Process Flow
|
|
21
|
+
|
|
22
|
+
```mermaid
|
|
23
|
+
flowchart TD
|
|
24
|
+
A[Define Currency] --> B{Is First Currency?}
|
|
25
|
+
B -->|Yes| C[Set as Base Currency]
|
|
26
|
+
B -->|No| D[Add to Available Currencies]
|
|
27
|
+
C --> E[Currency Active]
|
|
28
|
+
D --> E
|
|
29
|
+
E --> F[Available for Transactions]
|
|
30
|
+
F --> G[Products Can Set Prices]
|
|
31
|
+
F --> H[Orders Can Use Currency]
|
|
32
|
+
F --> I[Exchange Rates Can Reference]
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Scenario Patterns
|
|
36
|
+
|
|
37
|
+
- **Initial Setup**: Administrator defines base currency (e.g., USD) and common trading currencies (EUR, GBP, JPY) during system initialization
|
|
38
|
+
- **Market Expansion**: Business enters new market and adds local currency (e.g., BRL for Brazil expansion)
|
|
39
|
+
- **Currency Deactivation**: Obsolete currency (e.g., legacy national currency replaced by EUR) is deactivated to prevent new transactions while preserving historical data
|
|
40
|
+
- **Precision Configuration**: Cryptocurrency or precious metal tracking requires higher decimal precision than standard currencies
|
|
41
|
+
|
|
42
|
+
## Test Cases
|
|
43
|
+
|
|
44
|
+
- Creating a currency with valid ISO 4217 code should succeed
|
|
45
|
+
- Currency codes must be unique (no duplicate USD)
|
|
46
|
+
- First currency created should automatically become base currency
|
|
47
|
+
- Changing base currency should be allowed only with proper authorization
|
|
48
|
+
- Deactivating the base currency should be prevented
|
|
49
|
+
- Currency with active transactions should not be deletable (only deactivatable)
|
|
50
|
+
- Decimal places must be non-negative integer (0-4 typical range)
|
|
51
|
+
|
|
52
|
+
## Reference Links
|
|
53
|
+
|
|
54
|
+
- [ISO 4217 Currency Codes](https://www.iso.org/iso-4217-currency-codes.html)
|
|
55
|
+
- [Unicode CLDR Currency Data](https://cldr.unicode.org/index/downloads)
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# Exchange Rates
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
Exchange Rates maintain the conversion ratios between currency pairs with effective dates. Each rate record specifies the source currency, target currency, rate value, and the date from which it applies. The system uses these rates to convert monetary amounts for transactions, reporting, and consolidation.
|
|
6
|
+
|
|
7
|
+
Rates are date-based to support historical accuracy - a transaction from last month uses last month's rate, not today's rate.
|
|
8
|
+
|
|
9
|
+
## Business Purpose
|
|
10
|
+
|
|
11
|
+
Multi-currency operations require accurate exchange rate management:
|
|
12
|
+
|
|
13
|
+
- **Transaction Recording**: Convert foreign currency invoices to base currency at booking time
|
|
14
|
+
- **Financial Reporting**: Consolidate subsidiaries using period-end rates
|
|
15
|
+
- **Historical Accuracy**: Audit trail requires rates as of transaction date
|
|
16
|
+
- **Variance Analysis**: Compare budgeted rates vs actual rates for currency exposure
|
|
17
|
+
|
|
18
|
+
Exchange rates ensure monetary consistency while maintaining complete audit traceability.
|
|
19
|
+
|
|
20
|
+
## Process Flow
|
|
21
|
+
|
|
22
|
+
```mermaid
|
|
23
|
+
flowchart TD
|
|
24
|
+
A[Create Exchange Rate] --> B[Set Currency Pair]
|
|
25
|
+
B --> C[Set Rate Value]
|
|
26
|
+
C --> D[Set Effective Date]
|
|
27
|
+
D --> E{Validate Rate}
|
|
28
|
+
E -->|Invalid| F[Return Error]
|
|
29
|
+
E -->|Valid| G[Save Rate]
|
|
30
|
+
G --> H[Rate Available for Date Range]
|
|
31
|
+
|
|
32
|
+
I[Convert Amount] --> J[Find Rate for Date]
|
|
33
|
+
J --> K{Rate Found?}
|
|
34
|
+
K -->|No| L[Return Error or Use Fallback]
|
|
35
|
+
K -->|Yes| M[Apply Rate × Amount]
|
|
36
|
+
M --> N[Return Converted Amount]
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Scenario Patterns
|
|
40
|
+
|
|
41
|
+
- **Daily Rate Updates**: Finance team updates rates daily from central bank or market data feed
|
|
42
|
+
- **Period-End Rates**: Month-end closing uses official rates for consolidation
|
|
43
|
+
- **Historical Lookup**: Generating report for Q1 uses Q1 rates, not current rates
|
|
44
|
+
- **Rate Gap Handling**: Transaction on holiday uses most recent prior rate when exact date unavailable
|
|
45
|
+
- **Inverse Calculation**: Rate for USD→EUR automatically provides EUR→USD by inversion
|
|
46
|
+
|
|
47
|
+
## Test Cases
|
|
48
|
+
|
|
49
|
+
- Creating rate with valid currency pair and positive rate should succeed
|
|
50
|
+
- Rate with zero or negative value should fail validation
|
|
51
|
+
- Rate effective date in far future should be allowed (forward rates)
|
|
52
|
+
- Looking up rate for date should return most recent rate on or before that date
|
|
53
|
+
- Looking up rate with no prior rate should return error or configurable fallback
|
|
54
|
+
- Same currency conversion (USD→USD) should return rate of 1.0
|
|
55
|
+
- Inverse rate calculation should be mathematically correct (1/rate)
|
|
56
|
+
- Updating existing rate for same date should replace previous value
|
|
57
|
+
|
|
58
|
+
## Reference Links
|
|
59
|
+
|
|
60
|
+
- [European Central Bank Exchange Rates](https://www.ecb.europa.eu/stats/policy_and_exchange_rates/euro_reference_exchange_rates/html/index.en.html)
|
|
61
|
+
- [Open Exchange Rates API](https://openexchangerates.org/)
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# Unit Conversion
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
Unit Conversion enables automatic quantity transformation between any two units within the same category. The conversion uses the reference unit as an intermediary, ensuring consistent results regardless of which units are involved. This feature supports the core ERP operations where quantities must be expressed in different units for purchasing, inventory, and sales.
|
|
6
|
+
|
|
7
|
+
Conversions include configurable rounding precision to match business requirements for different unit types.
|
|
8
|
+
|
|
9
|
+
## Business Purpose
|
|
10
|
+
|
|
11
|
+
Different stakeholders work with different units:
|
|
12
|
+
|
|
13
|
+
- **Purchasing** buys in bulk units (cases, pallets, drums)
|
|
14
|
+
- **Warehouse** tracks in standardized units (pieces, kilograms, liters)
|
|
15
|
+
- **Sales** sells in customer-friendly units (packs, bottles, individual items)
|
|
16
|
+
- **Manufacturing** measures in precise units (grams, milliliters)
|
|
17
|
+
|
|
18
|
+
Unit conversion eliminates manual calculation errors and ensures inventory accuracy when the same product moves through these different contexts.
|
|
19
|
+
|
|
20
|
+
## Process Flow
|
|
21
|
+
|
|
22
|
+
```mermaid
|
|
23
|
+
flowchart TD
|
|
24
|
+
A[Conversion Request] --> B{Same Category?}
|
|
25
|
+
B -->|No| C[Return Error: Incompatible Units]
|
|
26
|
+
B -->|Yes| D[Get Source Unit Factor]
|
|
27
|
+
D --> E[Get Target Unit Factor]
|
|
28
|
+
E --> F[Calculate: Qty × Source Factor ÷ Target Factor]
|
|
29
|
+
F --> G[Apply Rounding Precision]
|
|
30
|
+
G --> H[Return Converted Quantity]
|
|
31
|
+
|
|
32
|
+
subgraph Validation
|
|
33
|
+
B
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
subgraph Calculation
|
|
37
|
+
D
|
|
38
|
+
E
|
|
39
|
+
F
|
|
40
|
+
G
|
|
41
|
+
end
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## Scenario Patterns
|
|
45
|
+
|
|
46
|
+
- **Purchase to Inventory**: Vendor ships 10 cases (12 units/case), system records 120 pieces in inventory
|
|
47
|
+
- **Sales Order Fulfillment**: Customer orders 5 kg, warehouse picks 5000 grams from bin tracked in grams
|
|
48
|
+
- **Manufacturing Consumption**: Recipe calls for 500ml, inventory deducts 0.5 liters from stock
|
|
49
|
+
- **Cross-Unit Reporting**: Generate report showing total weight in both kilograms and pounds for different markets
|
|
50
|
+
- **Fractional Handling**: Order for 2.5 dozen converts to 30 pieces for picking
|
|
51
|
+
|
|
52
|
+
## Test Cases
|
|
53
|
+
|
|
54
|
+
- Converting between units in the same category should return correct result
|
|
55
|
+
- Converting between units in different categories should return an error
|
|
56
|
+
- Converting with the same source and target unit should return the original quantity
|
|
57
|
+
- Converting to/from the reference unit should use factor of 1.0
|
|
58
|
+
- Rounding should respect the target unit's precision setting
|
|
59
|
+
- Zero quantity conversion should return zero
|
|
60
|
+
- Negative quantity conversion should be handled consistently (error or allow based on business rules)
|
|
61
|
+
- Very large quantities should not cause overflow errors
|
|
62
|
+
|
|
63
|
+
## Reference Links
|
|
64
|
+
|
|
65
|
+
- [NIST Unit Conversion Guide](https://www.nist.gov/pml/owm/metric-si/unit-conversion)
|
|
66
|
+
- [Odoo UoM Conversion Documentation](https://www.odoo.com/documentation/19.0/applications/inventory_and_mrp/inventory/product_management/configure/uom.html)
|