Open 2 terminals: one for the API and one for the Web app.
cd src/ShippingRules.API
dotnet runAPI base URL:
http://localhost:8080- Swagger UI:
http://localhost:8080(root)
Port config:
cd src/ShippingRules.Web
dotnet runWeb URL:
http://localhost:5014
API base for Web:
Install workload (one time):
dotnet workload install mauiRun:
cd src/ShippingRules.MAUI
dotnet runMAUI API base URL:
- Android emulator:
http://10.0.2.2:8080/api - Desktop:
http://localhost:8080/api
Config:
Web:
- Page:
http://localhost:5014/create-rule - File: src/ShippingRules.Web/Pages/CreateRule.razor
MAUI:
- Page: Create Rule
- File: src/ShippingRules.MAUI/Views/CreateRulePage.xaml
API used:
POST /api/ShippingRules- Controller:
ShippingRules.API.Controllers.ShippingRulesController.Create
Important inputs:
- Rule Type (string): must match exactly (example:
PortCharge,FreightCharge) - Precedence Level: 1=Vessel, 2=Port, 3=Principal, 4=Country, 5=Global
- Effective From/To: date window for when the rule applies
Web:
- Page:
http://localhost:5014/validate-rule - File: src/ShippingRules.Web/Pages/ValidateRule.razor
Pick:
- Country / Port / Principal / Vessel (optional, depending on rule)
- Rule Type
- Effective Date
API used:
GET /api/ShippingRules/applicable- Controller:
ShippingRules.API.Controllers.ShippingRulesController.GetApplicableRule
In the same Validate page:
- Enter Base Amount
- Click Calculate Cost
API used:
POST /api/ShippingRules/calculate-cost- Controller:
ShippingRules.API.Controllers.ShippingRulesController.CalculateCost
Rule selection is handled by:
The system filters rules by:
RuleType- Effective range:
EffectiveFrom <= EffectiveDate <= EffectiveTo (if set) IsActive == true
Then it picks the most specific match by precedence:
- Vessel-specific
- Port-specific
- Principal-specific
- Country-specific
- Global default
Precedence consistency validation:
Formula (as implemented):
Calculation helper:
If RequiresApproval = true on creation:
- The rule is created as Pending / Inactive
- It will not be applied until approved
Approve a rule:
POST /api/ShippingRules/{id}/approve- Controller:
ShippingRules.API.Controllers.ShippingRulesController.ApproveRule
Entity fields:
ShippingRules.Domain.Entities.ShippingRule.RequiresApprovalShippingRules.Domain.Entities.ShippingRule.ApprovedByShippingRules.Domain.Entities.ShippingRule.ApprovedAt
On create, the system checks for overlapping rules (same criteria + same RuleType + overlapping effective dates).
If conflicts exist, the API returns 409 Conflict with conflict details.
Repository support:
Exchange rates are stored in:
API:
GET /api/master/fx-rate?from=USD&to=INR&at=2025-12-20T00:00:00Z
Cost conversion (optional):
POST /api/ShippingRules/calculate-costwithTargetCurrency
Batch cost calculation:
POST /api/ShippingRules/batch-calculate-cost
Implementation: