138 lines
6.2 KiB
Go
138 lines
6.2 KiB
Go
package controllers
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"doormile/constants"
|
|
)
|
|
|
|
// The bulk-upload test sheet, checked against the rule that actually decides.
|
|
//
|
|
// krow_talent_app/tests/fixtures/doormile-logistics-test.xlsx carries 16 rows
|
|
// and an "Expected Routing" column saying, in words, what each one should do.
|
|
// That column is only a claim until something checks it, and the thing that
|
|
// decides is here, in Go — so it is checked here rather than restated in a
|
|
// JavaScript test, which would only prove that two copies of the rule agree
|
|
// with each other.
|
|
//
|
|
// If a row of the sheet is edited, this table is what says whether the sheet is
|
|
// still testing what it says it tests.
|
|
//
|
|
// Pickup is the sheet's single sender: Jayanthi's kitchen, Edayarpalayam,
|
|
// Coimbatore 641025.
|
|
const (
|
|
sheetPickupPincode = "641025"
|
|
sheetPickupLat = 11.0168
|
|
sheetPickupLng = 76.9558
|
|
)
|
|
|
|
func TestBulkTestSheetRoutesAsDocumented(t *testing.T) {
|
|
cases := []struct {
|
|
row int
|
|
receiver string
|
|
pincode string
|
|
lat, lng float64
|
|
wantLocal bool
|
|
wantAction string
|
|
wantConsStat string // with the hub-handover flow ON
|
|
why string
|
|
}{
|
|
// Customer -> Base. A different postal area, so the parcel cannot be
|
|
// carried to the receiver by the collecting rider.
|
|
{1, "Suresh Kumar", "600001", 13.091, 80.285, false, constants.NextActionInwardAtHub, constants.ConsignmentCreated, "641 -> 600, Chennai"},
|
|
{2, "Priya Raghavan", "600028", 13.018, 80.256, false, constants.NextActionInwardAtHub, constants.ConsignmentCreated, "641 -> 600, Chennai"},
|
|
{3, "Anil Reddy", "500081", 17.44, 78.3489, false, constants.NextActionInwardAtHub, constants.ConsignmentCreated, "interstate, Hyderabad"},
|
|
{4, "Meera Krishnan", "500032", 17.4156, 78.3378, false, constants.NextActionInwardAtHub, constants.ConsignmentCreated, "interstate with COD"},
|
|
{5, "Rahul Menon", "560001", 12.975, 77.606, false, constants.NextActionInwardAtHub, constants.ConsignmentCreated, "interstate, Bengaluru"},
|
|
{6, "Divya Nair", "560066", 12.9698, 77.75, false, constants.NextActionInwardAtHub, constants.ConsignmentCreated, "interstate with COD"},
|
|
{7, "Karthik Subramani", "625001", 9.9195, 78.119, false, constants.NextActionInwardAtHub, constants.ConsignmentCreated, "same state, different area"},
|
|
{8, "Lakshmi Devi", "636001", 11.664, 78.146, false, constants.NextActionInwardAtHub, constants.ConsignmentCreated, "same state, different area"},
|
|
|
|
// Customer -> Customer. The control group: if any of these routes to a
|
|
// base, the prefix rule has broken.
|
|
{9, "Ganesh Iyer", "641004", 11.029, 76.993, true, constants.NextActionDeliver, constants.ConsignmentOutForDelivery, "same 641 area"},
|
|
{10, "Revathi Balaji", "641012", 11.018, 76.966, true, constants.NextActionDeliver, constants.ConsignmentOutForDelivery, "same 641 area, COD"},
|
|
{11, "Vignesh Murugan", "641025", 11.008, 76.928, true, constants.NextActionDeliver, constants.ConsignmentOutForDelivery, "identical pincode"},
|
|
{12, "Anitha Selvam", "641038", 11.023, 76.945, true, constants.NextActionDeliver, constants.ConsignmentOutForDelivery, "same 641 area"},
|
|
|
|
// No pincode: the decision falls to straight-line distance. Both
|
|
// outcomes are present, because a fallback that only ever answers one
|
|
// way is not being tested.
|
|
{13, "Mohan Das", "", 11.05, 77.01, true, constants.NextActionDeliver, constants.ConsignmentOutForDelivery, "~8km, inside the 30km fallback"},
|
|
{14, "Sridhar Venkat", "", 13.0827, 80.2707, false, constants.NextActionInwardAtHub, constants.ConsignmentCreated, "~430km, far outside the fallback"},
|
|
{15, "Bhavani Shankar", "64", 13.06, 80.24, false, constants.NextActionInwardAtHub, constants.ConsignmentCreated, "2-digit pincode is unusable, distance decides"},
|
|
|
|
// The row that proves the prefix rule outranks distance.
|
|
{16, "Ramesh Palanisamy", "642001", 10.658, 77.008, false, constants.NextActionInwardAtHub, constants.ConsignmentCreated, "~40km but 642 is a different area"},
|
|
}
|
|
|
|
if len(cases) != 16 {
|
|
t.Fatalf("the sheet has 16 rows, this table has %d — they must not drift apart", len(cases))
|
|
}
|
|
|
|
for _, tc := range cases {
|
|
t.Run(tc.receiver, func(t *testing.T) {
|
|
gotLocal := isHyperlocalBooking(
|
|
sheetPickupPincode, tc.pincode,
|
|
sheetPickupLat, sheetPickupLng,
|
|
tc.lat, tc.lng,
|
|
)
|
|
if gotLocal != tc.wantLocal {
|
|
t.Fatalf("row %d (%s): hyperlocal = %v, want %v — %s",
|
|
tc.row, tc.receiver, gotLocal, tc.wantLocal, tc.why)
|
|
}
|
|
|
|
// What the rider is actually told to do with it, from the same
|
|
// helper pickup-complete and the queue read both use.
|
|
status := constants.ConsignmentCreated
|
|
if gotLocal {
|
|
status = constants.ConsignmentOutForDelivery
|
|
}
|
|
if status != tc.wantConsStat {
|
|
t.Errorf("row %d: consignment state %s, want %s", tc.row, status, tc.wantConsStat)
|
|
}
|
|
if got := nextActionForConsignment(status); got != tc.wantAction {
|
|
t.Errorf("row %d: next_action %s, want %s", tc.row, got, tc.wantAction)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
// The sheet is only worth uploading if it actually splits both ways. A file
|
|
// that turned out to be all-hyperlocal would pass every assertion above and
|
|
// still test nothing — which is exactly the problem with the tenant's own
|
|
// export that this sheet was written to replace.
|
|
func TestBulkTestSheetExercisesBothLegs(t *testing.T) {
|
|
type dest struct {
|
|
pincode string
|
|
lat, lng float64
|
|
}
|
|
dests := []dest{
|
|
{"600001", 13.091, 80.285}, {"600028", 13.018, 80.256},
|
|
{"500081", 17.44, 78.3489}, {"500032", 17.4156, 78.3378},
|
|
{"560001", 12.975, 77.606}, {"560066", 12.9698, 77.75},
|
|
{"625001", 9.9195, 78.119}, {"636001", 11.664, 78.146},
|
|
{"641004", 11.029, 76.993}, {"641012", 11.018, 76.966},
|
|
{"641025", 11.008, 76.928}, {"641038", 11.023, 76.945},
|
|
{"", 11.05, 77.01}, {"", 13.0827, 80.2707},
|
|
{"64", 13.06, 80.24}, {"642001", 10.658, 77.008},
|
|
}
|
|
|
|
var local, hub int
|
|
for _, d := range dests {
|
|
if isHyperlocalBooking(sheetPickupPincode, d.pincode, sheetPickupLat, sheetPickupLng, d.lat, d.lng) {
|
|
local++
|
|
} else {
|
|
hub++
|
|
}
|
|
}
|
|
|
|
if hub < 5 {
|
|
t.Errorf("only %d rows route through a base — too few to exercise the handover flow", hub)
|
|
}
|
|
if local < 3 {
|
|
t.Errorf("only %d rows go direct to the customer — no control group", local)
|
|
}
|
|
t.Logf("sheet splits %d base-handover / %d direct-to-customer", hub, local)
|
|
}
|