@deepintel-ltd/farmpro-contracts 1.11.12 → 1.14.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.
@@ -1 +1 @@
1
- {"version":3,"file":"market-intelligence.routes.d.ts","sourceRoot":"","sources":["../../src/routes/market-intelligence.routes.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAWxB,eAAO,MAAM,gCAAgC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAmB3C,CAAC;AAEH,eAAO,MAAM,wBAAwB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAgBnC,CAAC;AAEH,MAAM,MAAM,wBAAwB,GAAG,OAAO,wBAAwB,CAAC"}
1
+ {"version":3,"file":"market-intelligence.routes.d.ts","sourceRoot":"","sources":["../../src/routes/market-intelligence.routes.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAoBxB,QAAA,MAAM,yBAAyB;;;;;;;;;;IAU7B;;;OAGG;;;IAGH,gEAAgE;;IAEhE,qFAAqF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAErF,CAAC;AAEH,eAAO,MAAM,gCAAgC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QAZ3C;;;WAGG;;;QAGH,gEAAgE;;QAEhE,qFAAqF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAwBrF,CAAC;AAEH,eAAO,MAAM,6BAA6B;;;;;;;;;;;;;;;;;;;;;EAiBxC,CAAC;AAEH,eAAO,MAAM,uBAAuB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAWlC,CAAC;AAEH,eAAO,MAAM,wBAAwB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;oBAlEnC;;;uBAGG;;;oBAGH,gEAAgE;;oBAEhE,qFAAqF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA+GrF,CAAC;AAEH,MAAM,MAAM,wBAAwB,GAAG,OAAO,wBAAwB,CAAC;AACvE,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,yBAAyB,CAAC,CAAC;AAC5E,MAAM,MAAM,uBAAuB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,6BAA6B,CAAC,CAAC;AACpF,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAC"}
@@ -7,6 +7,35 @@ const marketProjectionSchema = z.object({
7
7
  outlook: z.string(),
8
8
  details: z.string(),
9
9
  });
10
+ const priceSourceSchema = z.enum([
11
+ 'farm_recent',
12
+ 'farm',
13
+ 'farm_report',
14
+ 'platform',
15
+ 'public',
16
+ 'none',
17
+ ]);
18
+ const cropPriceProjectionSchema = z.object({
19
+ crop: z.string(),
20
+ unit: z.string(),
21
+ currency: z.string(),
22
+ farmAveragePrice: z.number().nullable(),
23
+ farmRecentAveragePrice: z.number().nullable(),
24
+ farmSaleCount: z.number().int().nonnegative(),
25
+ farmLastSaleDate: z.string().datetime().nullable(),
26
+ platformAveragePrice: z.number().nullable(),
27
+ platformFarmCount: z.number().int().nonnegative(),
28
+ /**
29
+ * Best estimate for planning:
30
+ * farm recent → farm all-time → farm report → platform (sales + corroborated reports) → public
31
+ */
32
+ projectedPrice: z.number().nullable(),
33
+ source: priceSourceSchema,
34
+ /** Farm avg vs platform avg (%); null if either side missing */
35
+ vsPlatformPercent: z.number().nullable(),
36
+ /** Sum of field area (ha) for this crop on the farm; null if unknown / sales-only */
37
+ areaHa: z.number().nullable().optional(),
38
+ });
10
39
  export const marketIntelligenceOverviewSchema = z.object({
11
40
  farmId: z.string().uuid(),
12
41
  domesticSummary: z
@@ -24,9 +53,42 @@ export const marketIntelligenceOverviewSchema = z.object({
24
53
  })
25
54
  .nullable(),
26
55
  projections: z.array(marketProjectionSchema),
56
+ priceProjections: z.array(cropPriceProjectionSchema),
27
57
  eudrAlertTitle: z.string().nullable(),
28
58
  updatedAt: z.string().datetime(),
29
59
  });
60
+ export const createMarketPriceReportSchema = z.object({
61
+ crop: z.string().min(1).max(100),
62
+ pricePerUnit: z.number().positive().max(10_000_000),
63
+ unit: z
64
+ .string()
65
+ .min(1)
66
+ .max(50)
67
+ .optional()
68
+ .transform((u) => {
69
+ const raw = (u || 'kg').trim().toLowerCase();
70
+ if (!raw)
71
+ return 'kg';
72
+ if (raw === 'kilogram' || raw === 'kilograms')
73
+ return 'kg';
74
+ return raw;
75
+ }),
76
+ currency: z.enum(['NGN', 'USD']).optional(),
77
+ observedAt: z.string().datetime().optional(),
78
+ marketLabel: z.string().max(80).optional().nullable(),
79
+ });
80
+ export const marketPriceReportSchema = z.object({
81
+ id: z.string().uuid(),
82
+ farmId: z.string().uuid(),
83
+ crop: z.string(),
84
+ cropKey: z.string(),
85
+ pricePerUnit: z.number(),
86
+ unit: z.string(),
87
+ currency: z.string(),
88
+ observedAt: z.string().datetime(),
89
+ marketLabel: z.string().nullable(),
90
+ createdAt: z.string().datetime(),
91
+ });
30
92
  export const marketIntelligenceRouter = c.router({
31
93
  getOverview: {
32
94
  method: 'GET',
@@ -40,6 +102,40 @@ export const marketIntelligenceRouter = c.router({
40
102
  404: jsonApiErrorResponseSchema,
41
103
  },
42
104
  summary: 'Farm market intelligence overview',
43
- description: 'National market summaries and crop projections for sell-window decisions',
105
+ description: 'National market summaries plus crop price projections: farm sales, farm reports, platform knowledge, then public reference',
106
+ },
107
+ createPriceReport: {
108
+ method: 'POST',
109
+ path: '/farms/:farmId/market-intelligence/price-reports',
110
+ pathParams: z.object({
111
+ farmId: z.string().uuid(),
112
+ }),
113
+ body: createMarketPriceReportSchema,
114
+ responses: {
115
+ 201: marketPriceReportSchema,
116
+ 400: jsonApiErrorResponseSchema,
117
+ 401: jsonApiErrorResponseSchema,
118
+ 403: jsonApiErrorResponseSchema,
119
+ 404: jsonApiErrorResponseSchema,
120
+ },
121
+ summary: 'Submit a market price report',
122
+ description: 'Record an overheard / local market price. Trusted immediately for this farm; shared only after corroboration.',
123
+ },
124
+ listPriceReports: {
125
+ method: 'GET',
126
+ path: '/farms/:farmId/market-intelligence/price-reports',
127
+ pathParams: z.object({
128
+ farmId: z.string().uuid(),
129
+ }),
130
+ query: z.object({
131
+ days: z.coerce.number().int().min(1).max(365).optional().default(90),
132
+ }),
133
+ responses: {
134
+ 200: z.object({ data: z.array(marketPriceReportSchema) }),
135
+ 401: jsonApiErrorResponseSchema,
136
+ 403: jsonApiErrorResponseSchema,
137
+ 404: jsonApiErrorResponseSchema,
138
+ },
139
+ summary: 'List recent market price reports for a farm',
44
140
  },
45
141
  });