Skip to content

Commit 260409d

Browse files
committed
Standardize product fields to snake_case
Refactor: convert product-related fields from camelCase to snake_case across models, components and payload transformer to match API naming. Add warehouses models and WarehousesService and wire warehouseOptions into product workspace and general tab. Extend ProductResponse with richer types (units, part_origin, oem_codes, equivalents, applications, suppliers, created_at/updated_at) and adjust nullable/primitives (active, pricing, inventory). Also minor fixes: select equality check, promotional date nullability, and validation/payload mapping updates to use snake_case.
1 parent b2285b4 commit 260409d

19 files changed

Lines changed: 293 additions & 168 deletions

src/app/core/models/products/product-create.model.ts

Lines changed: 41 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,14 @@ import { DSelectOption } from '../design-system/select-option.model';
33

44
/** Estado interno do formulário de criação (campos do POST) */
55
export interface ProductCreateFormState {
6-
categoryId: string;
7-
manufacturerId: string;
8-
partOriginId: string;
9-
unitId: string;
10-
internalCode: string;
6+
category_id: string;
7+
manufacturer_id: string;
8+
part_origin_id: string;
9+
unit_id: string;
10+
internal_code: string;
1111
barcode: string;
1212
name: string;
13-
shortDescription: string;
13+
short_description: string;
1414
description: string;
1515
weight: number;
1616
height: number;
@@ -21,14 +21,14 @@ export interface ProductCreateFormState {
2121

2222
export function defaultProductCreateFormState(): ProductCreateFormState {
2323
return {
24-
categoryId: '',
25-
manufacturerId: '',
26-
partOriginId: '',
27-
unitId: '',
28-
internalCode: '',
24+
category_id: '',
25+
manufacturer_id: '',
26+
part_origin_id: '',
27+
unit_id: '',
28+
internal_code: '',
2929
barcode: '',
3030
name: '',
31-
shortDescription: '',
31+
short_description: '',
3232
description: '',
3333
weight: 0,
3434
height: 0,
@@ -42,7 +42,7 @@ export function createFormToGeneralSource(state: ProductCreateFormState): Produc
4242
return {
4343
...state,
4444
slug: '',
45-
statusId: '',
45+
status_id: '',
4646
active: true,
4747
};
4848
}
@@ -69,15 +69,15 @@ export interface CreateProductPayload {
6969
export interface ProductGeneralFormData {
7070
name: string;
7171
slug: string;
72-
shortDescription: string;
72+
short_description: string;
7373
description: string;
74-
categoryId: string;
75-
manufacturerId: string;
76-
partOriginId: string;
77-
statusId: string;
78-
internalCode: string;
74+
category_id: string;
75+
manufacturer_id: string;
76+
part_origin_id: string;
77+
status_id: string;
78+
internal_code: string;
7979
barcode: string;
80-
unitId: string;
80+
unit_id: string;
8181
weight: number;
8282
height: number;
8383
width: number;
@@ -94,20 +94,21 @@ export interface ProductGeneralFormOptions {
9494
partOriginOptions: DSelectOption[];
9595
unitOptions: DSelectOption[];
9696
statusOptions: DSelectOption[];
97+
warehouseOptions: DSelectOption[];
9798
}
9899

99100
export interface ProductGeneralFormSource {
100101
name: string;
101102
slug: string;
102-
shortDescription: string;
103+
short_description: string;
103104
description: string;
104-
categoryId: string;
105-
manufacturerId: string;
106-
partOriginId: string;
107-
statusId: string;
108-
internalCode: string;
105+
category_id: string;
106+
manufacturer_id: string;
107+
part_origin_id: string;
108+
status_id: string;
109+
internal_code: string;
109110
barcode: string;
110-
unitId: string;
111+
unit_id: string;
111112
weight: number;
112113
height: number;
113114
width: number;
@@ -120,15 +121,15 @@ export function toProductGeneralFormData(source: ProductGeneralFormSource): Prod
120121
return {
121122
name: source.name,
122123
slug: source.slug,
123-
shortDescription: source.shortDescription,
124+
short_description: source.short_description,
124125
description: source.description,
125-
categoryId: source.categoryId,
126-
manufacturerId: source.manufacturerId,
127-
partOriginId: source.partOriginId,
128-
statusId: source.statusId,
129-
internalCode: source.internalCode,
126+
category_id: source.category_id,
127+
manufacturer_id: source.manufacturer_id,
128+
part_origin_id: source.part_origin_id,
129+
status_id: source.status_id,
130+
internal_code: source.internal_code,
130131
barcode: source.barcode,
131-
unitId: source.unitId,
132+
unit_id: source.unit_id,
132133
weight: source.weight,
133134
height: source.height,
134135
width: source.width,
@@ -140,14 +141,14 @@ export function toProductGeneralFormData(source: ProductGeneralFormSource): Prod
140141

141142
export function toCreateProductPayload(source: ProductGeneralFormSource): CreateProductPayload {
142143
return {
143-
category_id: source.categoryId,
144-
manufacturer_id: source.manufacturerId,
145-
part_origin_id: source.partOriginId,
146-
unit_id: source.unitId,
147-
internal_code: source.internalCode,
144+
category_id: source.category_id,
145+
manufacturer_id: source.manufacturer_id,
146+
part_origin_id: source.part_origin_id,
147+
unit_id: source.unit_id,
148+
internal_code: source.internal_code,
148149
barcode: source.barcode,
149150
name: source.name,
150-
short_description: source.shortDescription,
151+
short_description: source.short_description,
151152
description: source.description,
152153
weight: source.weight,
153154
height: source.height,

src/app/core/models/products/product-form-state.model.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ export interface ProductFormState {
44
category_id: string;
55
manufacturer_id: string;
66
unit: string;
7-
status_id: string;
7+
unit_id: string;
88
slug: string;
99
description: string;
1010

src/app/core/models/products/product-request.model.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ export interface UpdateProductPayload {
7979
category_id?: string | null;
8080
manufacturer_id?: string | null;
8181
part_origin_id?: string | null;
82-
status_id?: string | null;
82+
unit_id?: string | null;
8383

8484
internal_code?: string | null;
8585
barcode?: string | null;

src/app/core/models/products/product-response.model.ts

Lines changed: 95 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,51 @@
1+
import {
2+
OemCodeItem,
3+
SupplierItem,
4+
} from '../../../features/catalog/models/product-workspace.model';
5+
16
export interface ProductResponse extends Record<string, unknown> {
27
id: string;
8+
39
status: Status;
410
category: Category;
511
manufacturer: Category;
12+
part_origin: PartOrigin | null;
13+
unit: Unit | null;
14+
615
internal_code: string;
16+
barcode: string | null;
17+
718
name: string;
819
slug: string;
9-
icon: null;
10-
image: null;
11-
short_description: string;
20+
21+
icon: string | null;
22+
image: string | null;
23+
24+
short_description: string | null;
1225
description: string;
26+
1327
weight: string;
1428
height: string;
1529
width: string;
1630
length: string;
31+
1732
featured: boolean;
18-
active: number;
33+
active: boolean;
34+
1935
is_sellable: boolean;
2036
commercial_status: string;
21-
pricing: Pricing;
22-
inventory: Inventory;
37+
38+
pricing: Pricing | null;
39+
40+
inventory: Inventory | null;
41+
42+
oem_codes: OemCodeItem[];
43+
equivalents: SupplierItem[];
44+
applications: VehicleApplication[];
45+
suppliers: SupplierItem[];
46+
47+
created_at: string;
48+
updated_at: string;
2349
}
2450

2551
export interface Inventory {
@@ -63,3 +89,66 @@ export interface Status {
6389
color: string;
6490
icon: string;
6591
}
92+
93+
export interface OemCode {
94+
id: string;
95+
code: string;
96+
is_main: boolean;
97+
manufacturer: Category;
98+
manufacturer_code: string;
99+
created_at: string;
100+
updated_at: string;
101+
}
102+
103+
export interface EquivalentProduct {
104+
id: string;
105+
type: string;
106+
reference_code: string;
107+
manufacturer: Category;
108+
manufacturer_code: string;
109+
is_main: boolean;
110+
created_at: string;
111+
updated_at: string;
112+
}
113+
114+
export interface VehicleApplication {
115+
id: string;
116+
manufacturer: string;
117+
model: string;
118+
year_from: number;
119+
year_to: number | null;
120+
engine: string | null;
121+
details: string | null;
122+
created_at: string;
123+
updated_at: string;
124+
}
125+
126+
// export interface Supplier {
127+
// id: string;
128+
// name: string;
129+
// code: string | null;
130+
// cost_price: number;
131+
// delivery_time_days: number | null;
132+
// minimum_order_quantity: number;
133+
// active: boolean;
134+
// created_at: string;
135+
// updated_at: string;
136+
// }
137+
138+
export interface Unit {
139+
id: string;
140+
code: string;
141+
name: string;
142+
abbreviation: string;
143+
is_base: boolean;
144+
created_at: string;
145+
updated_at: string;
146+
}
147+
148+
export interface PartOrigin {
149+
id: string;
150+
name: string;
151+
code: string;
152+
created_at: string;
153+
updated_at: string;
154+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
export interface WarehouseOptionsResponse {
2+
success: boolean;
3+
message: string;
4+
data: WarehouseOption[];
5+
}
6+
7+
export interface WarehouseOption {
8+
id: string;
9+
label: string;
10+
description: string;
11+
icon: string;
12+
}

src/app/core/models/warehouses/warehouses.interface.ts

Whitespace-only changes.
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import { HttpClient } from '@angular/common/http';
2+
import { inject, Injectable } from '@angular/core';
3+
import { PaginatedResponse } from '../models/pagination/pagination.model';
4+
import { environment } from '../../../environments/environment';
5+
import { WarehouseOptionsResponse } from '../models/warehouses/warehouse-options.model';
6+
import { GeneralOptionQuery } from '../models/generals/general-option-query.model';
7+
import { buildHttpParams } from './build-http-params';
8+
9+
@Injectable({
10+
providedIn: 'root',
11+
})
12+
export class WarehousesService {
13+
private http = inject(HttpClient);
14+
private api = environment.apiUrl;
15+
private flag = 'warehouses';
16+
17+
getAll() {
18+
return this.http.get<PaginatedResponse<WarehouseOptionsResponse>>(`${this.api}/${this.flag}`);
19+
}
20+
21+
getOptions(filters: GeneralOptionQuery) {
22+
const params = buildHttpParams(filters);
23+
return this.http.get<WarehouseOptionsResponse>(`${this.api}/${this.flag}/options`, { params });
24+
}
25+
}

src/app/core/utils/product-payload.transformer.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,11 @@ export function toNullableDate(val: unknown): string | null {
5353
}
5454

5555
function hasPromotionalPrice(promotionalPrice: number | null): boolean {
56-
return promotionalPrice !== null && promotionalPrice !== undefined && String(promotionalPrice).trim() !== '';
56+
return (
57+
promotionalPrice !== null &&
58+
promotionalPrice !== undefined &&
59+
String(promotionalPrice).trim() !== ''
60+
);
5761
}
5862

5963
function buildPriceBlock(state: ProductFormState) {
@@ -81,7 +85,7 @@ function buildProductRoot(state: ProductFormState) {
8185
return {
8286
category_id: toNullableString(state.category_id),
8387
manufacturer_id: toNullableString(state.manufacturer_id),
84-
status_id: toNullableString(state.status_id),
88+
unit_id: toNullableString(state.unit_id),
8589
internal_code: toNullableString(state.internal_code),
8690
name: toNullableString(state.name),
8791
slug: toNullableString(state.slug),
@@ -151,8 +155,8 @@ export function validateProductForm(
151155
if (!state.unit) {
152156
errs['unit_id'] = 'Selecione a unidade de medida.';
153157
}
154-
if (!state.status_id) {
155-
errs['status_id'] = 'Selecione o status do produto.';
158+
if (!state.unit_id) {
159+
errs['unit_id'] = 'Selecione o status do produto.';
156160
}
157161

158162
if (isCreateFlow) {

src/app/design-system/select/select.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
<option
2525
[value]="option.value"
2626
[disabled]="option.disabled"
27-
[selected]="option.value === value()"
27+
[selected]="option.value == value()"
2828
>
2929
{{ option.label }}
3030
</option>

src/app/features/catalog/components/product-form/commercial-tab/commercial-tab.ts

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,15 @@ import { InputComponent } from '../../../../../design-system/input/input';
44
@Component({
55
selector: 'app-product-commercial-tab',
66
standalone: true,
7-
imports: [
8-
InputComponent
9-
],
7+
imports: [InputComponent],
108
changeDetection: ChangeDetectionStrategy.OnPush,
11-
templateUrl: './commercial-tab.html'
9+
templateUrl: './commercial-tab.html',
1210
})
1311
export class ProductCommercialTabComponent {
1412
readonly formPrice = input<number>(0);
1513
readonly formPromotionalPrice = input<number | null>(null);
16-
readonly formPromotionStartDate = input<string>('');
17-
readonly formPromotionEndDate = input<string>('');
14+
readonly formPromotionStartDate = input<string | null>(null);
15+
readonly formPromotionEndDate = input<string | null>(null);
1816
readonly formIsInvoiced = input<boolean>(true);
1917

2018
readonly isReadOnly = input<boolean>(false);

0 commit comments

Comments
 (0)