Merge branch 'main' of github.com:Poomipat-Ch/taobin_recipe_manager

This commit is contained in:
Kenta420 2024-01-19 17:54:07 +07:00
commit 45851422f7
20 changed files with 1216 additions and 593 deletions

View file

@ -2,22 +2,32 @@ import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { MaterialCode, MaterialSetting } from '../models/recipe.model'; import { MaterialCode, MaterialSetting } from '../models/recipe.model';
import { environment } from 'src/environments/environment'; import { environment } from 'src/environments/environment';
import { Observable } from 'rxjs'; import { Observable, count } from 'rxjs';
import { ActivatedRoute } from '@angular/router';
import { getCountryMapSwitcher } from 'src/app/shared/helpers/recipe';
import { AsyncStorage } from 'src/app/shared/helpers/asyncStorage';
@Injectable({ providedIn: 'root' }) @Injectable({ providedIn: 'root' })
export class MaterialService { export class MaterialService {
constructor(private _httpClient: HttpClient) {}
getMaterialCodes( private department = this._route.snapshot.paramMap.get('department')
constructor(private _httpClient: HttpClient, private _route: ActivatedRoute) {}
async getMaterialCodes(
matIds?: number[], matIds?: number[],
country?: string, country?: string,
filename?: string filename?: string
): Observable<MaterialCode[]> { ): Promise<Observable<MaterialCode[]>> {
// async country
let asyncCountry = await AsyncStorage.getItem<string>('currentRecipeCountry');
return this._httpClient.get<MaterialCode[]>( return this._httpClient.get<MaterialCode[]>(
`${environment.api}/materials/code`, `${environment.api}/materials/code`,
{ {
params: { params: {
country: country || this.getCurrentCountry(), country: country || asyncCountry,
filename: filename || this.getCurrentFile(), filename: filename || this.getCurrentFile(),
mat_ids: matIds?.join(',') || '', mat_ids: matIds?.join(',') || '',
}, },
@ -26,19 +36,26 @@ export class MaterialService {
); );
} }
getFullMaterialDetail( async getFullMaterialDetail(
country?: string, country?: string,
filename?: string filename?: string
): Observable<{ ): Promise<Observable<{
"materialId": number, "materialId": number,
"name": string, "name": string,
"type": string "type": string
}[] | null>{ }[] | null>>{
console.log("getFullMaterialDetail", country, filename); console.log("getFullMaterialDetail", country, "where filename = ",filename, "department.short = ", this.department!);
country = country || this.getCurrentCountry(); let currentCountryWithoutDepartment = await this.getCurrentCountry();
let asyncCountry = await this.getCurrentCountry(this.department!);
console.log("[FullMatFetchService] get current country = ", currentCountryWithoutDepartment, " do switch tuple = ", getCountryMapSwitcher(currentCountryWithoutDepartment));
country = getCountryMapSwitcher(currentCountryWithoutDepartment);
filename = filename || this.getCurrentFile(); filename = filename || this.getCurrentFile();
// finalize fetch from what?
console.log("country, filename", country, filename);
return this._httpClient.get<{ return this._httpClient.get<{
"materialId": number, "materialId": number,
"name": string, "name": string,
@ -48,16 +65,19 @@ export class MaterialService {
}); });
} }
getMaterialSettingById( async getMaterialSettingById(
id: number, id: number,
country?: string, country?: string,
filename?: string filename?: string
): Observable<MaterialSetting> { ): Promise<Observable<MaterialSetting>> {
let asyncCountry = await AsyncStorage.getItem<string>('currentRecipeCountry');
return this._httpClient.get<MaterialSetting>( return this._httpClient.get<MaterialSetting>(
`${environment.api}/materials/setting/${id}`, `${environment.api}/materials/setting/${id}`,
{ {
params: { params: {
country: country || this.getCurrentCountry(), country: country || asyncCountry,
filename: filename || this.getCurrentFile(), filename: filename || this.getCurrentFile(),
}, },
withCredentials: true, withCredentials: true,
@ -71,11 +91,30 @@ export class MaterialService {
return currentRecipeFile; return currentRecipeFile;
} }
return 'coffeethai02_580.json'; return 'default';
} }
getCurrentCountry(): string { async getCurrentCountry(department? : string): Promise<string> {
const currentRecipeCountry = localStorage.getItem('currentRecipeCountry');
// fetch by using department
if(department){
// translate back to full name
let fullname = getCountryMapSwitcher(department);
console.log('Material.service::fullname: ', fullname);
await AsyncStorage.setItem('currentRecipeCountry', fullname);
// localStorage.setItem('currentRecipeCountry', fullname);
return fullname;
}
// const currentRecipeCountry = localStorage.getItem('currentRecipeCountry');
const currentRecipeCountry = await AsyncStorage.getItem<string>('currentRecipeCountry');
if (currentRecipeCountry) { if (currentRecipeCountry) {
return currentRecipeCountry; return currentRecipeCountry;
} }

View file

@ -12,6 +12,9 @@ import {
} from '../models/recipe.model'; } from '../models/recipe.model';
import { environment } from 'src/environments/environment'; import { environment } from 'src/environments/environment';
import { RecipeMetaData } from 'src/app/shared/types/recipe'; import { RecipeMetaData } from 'src/app/shared/types/recipe';
import { getCountryMapSwitcher } from 'src/app/shared/helpers/recipe';
import { ActivatedRoute } from '@angular/router';
import { AsyncStorage } from 'src/app/shared/helpers/asyncStorage';
type RecipeOverviewParams = { type RecipeOverviewParams = {
filename: string; filename: string;
@ -38,15 +41,17 @@ export class RecipeService {
private tmp_files: string[] = []; private tmp_files: string[] = [];
private department = this._route.snapshot.paramMap.get('department');
private get tmpfiles(): string[] { private get tmpfiles(): string[] {
return this.tmp_files; return this.tmp_files;
} }
constructor(private _httpClient: HttpClient) {} constructor(private _httpClient: HttpClient, private _route: ActivatedRoute) {}
getRecipesDashboard( getRecipesDashboard(
params: RecipeDashboardParams = { params: any = {
country: this.getCurrentCountry(), country: this.getCurrentCountry(this.department!),
filename: this.getCurrentFile(), filename: this.getCurrentFile(),
} }
): Observable<RecipesDashboard> { ): Observable<RecipesDashboard> {
@ -63,16 +68,16 @@ export class RecipeService {
); );
} }
getRecipeOverview( async getRecipeOverview(
params: RecipeOverviewParams = { params: any = {
country: this.getCurrentCountry(), country: this.getCurrentCountry(this.department!),
filename: this.getCurrentFile(), filename: this.getCurrentFile(),
materialIds: [], materialIds: [],
offset: 0, offset: 0,
take: 20, take: 20,
search: '', search: '',
} }
): Observable<RecipeOverviewList> { ): Promise<Observable<RecipeOverviewList>> {
return this._httpClient.get<RecipeOverviewList>( return this._httpClient.get<RecipeOverviewList>(
environment.api + '/recipes/overview', environment.api + '/recipes/overview',
{ {
@ -90,13 +95,17 @@ export class RecipeService {
); );
} }
getRecipeDetail(productCode: string): Observable<RecipeDetail> { async getRecipeDetail(productCode: string): Promise<Observable<RecipeDetail>> {
let asyncCountry = await this.getCurrentCountry(this.department!);
console.log('get detail by asyncCountry', asyncCountry);
return this._httpClient.get<RecipeDetail>( return this._httpClient.get<RecipeDetail>(
environment.api + '/recipes/' + productCode, environment.api + '/recipes/' + productCode,
{ {
params: { params: {
filename: this.getCurrentFile(), filename: this.getCurrentFile(),
country: this.getCurrentCountry(), country: asyncCountry,
}, },
withCredentials: true, withCredentials: true,
responseType: 'json', responseType: 'json',
@ -104,15 +113,18 @@ export class RecipeService {
); );
} }
getRecipeDetailMat( async getRecipeDetailMat(
productCode: string productCode: string
): Observable<{ result: RecipeDetailMat[] }> { ): Promise<Observable<{ result: RecipeDetailMat[]; }>> {
let asyncCountry = await this.getCurrentCountry(this.department!);
return this._httpClient.get<{ result: RecipeDetailMat[] }>( return this._httpClient.get<{ result: RecipeDetailMat[] }>(
environment.api + '/recipes/' + productCode + '/mat', environment.api + '/recipes/' + productCode + '/mat',
{ {
params: { params: {
filename: this.getCurrentFile(), filename: this.getCurrentFile(),
country: this.getCurrentCountry(), country: asyncCountry,
}, },
withCredentials: true, withCredentials: true,
responseType: 'json', responseType: 'json',
@ -121,20 +133,41 @@ export class RecipeService {
} }
getCurrentFile(): string { getCurrentFile(): string {
// TODO: get default from server
const currentRecipeFile = localStorage.getItem('currentRecipeFile'); const currentRecipeFile = localStorage.getItem('currentRecipeFile');
if (currentRecipeFile) { if (currentRecipeFile) {
return currentRecipeFile; return currentRecipeFile;
} }
return 'coffeethai02_580.json'; return 'default';
} }
setCurrentFile(filename: string) { setCurrentFile(filename: string) {
localStorage.setItem('currentRecipeFile', filename); localStorage.setItem('currentRecipeFile', filename);
} }
getCurrentCountry(): string { async getCurrentCountry(department?: string): Promise<string> {
const currentRecipeCountry = localStorage.getItem('currentRecipeCountry');
if(department){
// translate back to full name
let fullname = getCountryMapSwitcher(department);
console.log('fullname: ', fullname);
// localStorage.setItem('currentRecipeCountry', fullname);
await AsyncStorage.setItem('currentRecipeCountry', fullname);
return fullname;
}
// const currentRecipeCountry = localStorage.getItem('currentRecipeCountry');
const currentRecipeCountry = await AsyncStorage.getItem<string>('currentRecipeCountry');
if (currentRecipeCountry) { if (currentRecipeCountry) {
return currentRecipeCountry; return currentRecipeCountry;
} }
@ -225,6 +258,7 @@ export class RecipeService {
} }
getSubMenus(country: string, filename: string, productCode: string) { getSubMenus(country: string, filename: string, productCode: string) {
console.log('getSubMenus', country, filename, productCode);
return this._httpClient.get<Recipe01[]>( return this._httpClient.get<Recipe01[]>(
environment.api + environment.api +
'/recipes/' + '/recipes/' +

View file

@ -1,16 +1,22 @@
import { HttpClient } from '@angular/common/http'; import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { Observable } from 'rxjs'; import { Observable, count } from 'rxjs';
import { environment } from 'src/environments/environment'; import { environment } from 'src/environments/environment';
import { Topping, ToppingSet } from '../models/recipe.model'; import { Topping, ToppingSet } from '../models/recipe.model';
import { RecipeService } from './recipe.service';
import { getCountryMapSwitcher } from 'src/app/shared/helpers/recipe';
@Injectable({ @Injectable({
providedIn: 'root', providedIn: 'root',
}) })
export class ToppingService { export class ToppingService {
constructor(private _httpClient: HttpClient) {} constructor(private _httpClient: HttpClient, private _recipeService: RecipeService) {}
getToppings(country: string, filename: string): Observable<Topping> { async getToppings(country: string, filename: string): Promise<Observable<Topping>> {
console.log("getToppings", country);
let asyncCountry = await this._recipeService.getCurrentCountry();
country = getCountryMapSwitcher(asyncCountry);
console.log("getToppingsPreFetch", country, asyncCountry);
return this._httpClient.get<Topping>( return this._httpClient.get<Topping>(
`${environment.api}/recipes/${country}/${filename}/toppings`, `${environment.api}/recipes/${country}/${filename}/toppings`,
{ {
@ -23,7 +29,11 @@ export class ToppingService {
); );
} }
getToppingsOfRecipe(country: string, filename: string, productCode: string): Observable<ToppingSet[]> { async getToppingsOfRecipe(country: string, filename: string, productCode: string): Promise<Observable<ToppingSet[]>> {
console.log("getToppingsOfRecipe", country);
let asyncCountry = await this._recipeService.getCurrentCountry();
country = country || asyncCountry;
console.log("getToppingsOfRecipePreFetch", country, asyncCountry);
return this._httpClient.get<ToppingSet[]>( return this._httpClient.get<ToppingSet[]>(
`${environment.api}/recipes/${country}/${filename}/${productCode}/toppings`, `${environment.api}/recipes/${country}/${filename}/${productCode}/toppings`,
{ {

View file

@ -7,19 +7,17 @@
class="block p-6 bg-white border border-gray-200 rounded-lg shadow w-full" class="block p-6 bg-white border border-gray-200 rounded-lg shadow w-full"
> >
<div *ngIf="isLoaded; else indicator" [@inOutAnimation]> <div *ngIf="isLoaded; else indicator" [@inOutAnimation]>
<!-- productCode -->
<div>
<!-- productCode --> <input
<div> class="input input-bordered input-xs text-lg text-gray-900 my-2"
<input type="text"
class="input input-bordered input-xs text-lg text-gray-900 my-2" name="productCode"
type="text" [value]="productCode"
name="productCode" (keyup)="onProductCodeChange($event)"
[value]="productCode" [disabled]="!isEditable()"
(keyup)="onProductCodeChange($event)" />
[disabled]="!isEditable()" </div>
/>
</div>
<div class="flex flex-wrap"> <div class="flex flex-wrap">
<h5 class="mb-2 text-xl font-bold text-gray-900"> <h5 class="mb-2 text-xl font-bold text-gray-900">
@ -29,7 +27,6 @@
<h5 class="mb-2 text-xl font-bold text-gray-900"> <h5 class="mb-2 text-xl font-bold text-gray-900">
{{ recipeDetailForm.getRawValue().otherName }} {{ recipeDetailForm.getRawValue().otherName }}
</h5> </h5>
</div> </div>
<div class="flex items-center mb-2"> <div class="flex items-center mb-2">
<div class="flex items-center"> <div class="flex items-center">
@ -110,7 +107,12 @@
<div *ngIf="hasSubmenu()"> <div *ngIf="hasSubmenu()">
<div *ngFor="let sub of listSubMenuProductcodes()"> <div *ngFor="let sub of listSubMenuProductcodes()">
<button class="btn btn-sm btn-primary m-2" (click)="selectSubmenu(sub)">{{sub}}</button> <button
class="btn btn-sm btn-primary m-2"
(click)="selectSubmenu(sub)"
>
{{ sub }}
</button>
</div> </div>
</div> </div>
</div> </div>
@ -118,45 +120,52 @@
</div> </div>
<div id="recipeList" class="carousel-item w-full"> <div id="recipeList" class="carousel-item w-full">
<div <div
class="overflow-auto h-[75vh] mb-4 rounded bg-white border border-gray-200 shadow w-1/2" class="overflow-auto h-[75vh] mb-4 rounded bg-white border border-gray-200 shadow"
> >
<app-recipe-list <app-recipe-list
[productCode]="productCode" [productCode]="productCode"
[isSubMenu]="false" [isSubMenu]="false"
(recipeListFormChange)="onRecipeListFormChange($event)" (recipeListFormChange)="onRecipeListFormChange($event)"
></app-recipe-list> ></app-recipe-list>
</div>
</div>
<div id="toppingSet" class="carousel-item w-full">
<div class="overflow-auto h-[75vh] mb-4 rounded bg-white border border-gray-200 shadow">
<app-recipe-toppingset
[productCode]="productCode"
(toppingSetChange)="onToppingListChange($event)"
></app-recipe-toppingset>
</div> </div>
</div> </div>
<!-- <div id="toppingSet" class="carousel-item w-full">
<div
class="overflow-auto h-[75vh] mb-4 rounded bg-white border border-gray-200 shadow max-w-screen-xl"
>
<app-recipe-toppingset
[productCode]="productCode"
(toppingSetChange)="onToppingListChange($event)"
></app-recipe-toppingset>
</div>
</div> -->
</div> </div>
<!-- try pop up modal --> <!-- try pop up modal -->
<!-- TODO: do topping --> <!-- TODO: do topping -->
<div <div
class="sticky bottom-0 col-span-3 max-w-screen-lg flex justify-end bg-white rounded-full drop-shadow-2xl p-3" class="sticky bottom-0 col-span-3 max-w-screen-lg flex justify-end bg-white rounded-full drop-shadow-2xl p-3"
> >
<div class="flex justify-center w-full start-0 py-2">
<div class="flex justify-center w-full start-0 py-2"> <a
<a href="{{department}}/recipe/{{productCode}}#name" class="btn btn-xs">1</a> href="{{ department }}/recipe/{{ productCode }}#name"
<a href="{{department}}/recipe/{{productCode}}#recipeList" class="btn btn-xs">2</a> class="btn btn-xs"
<a href="{{department}}/recipe/{{productCode}}#toppingSet" class="btn btn-xs">3</a> >1</a
</div> >
<a
href="{{ department }}/recipe/{{ productCode }}#recipeList"
class="btn btn-xs"
>2</a
>
<a
href="{{ department }}/recipe/{{ productCode }}#toppingSet"
class="btn btn-xs"
>3</a
>
</div>
<!-- <div> Commit Message </div> --> <!-- <div> Commit Message </div> -->
<!-- <p class="text-2xl mr-8 text-gray-400 dark:text-gray-500">Commit Message</p> --> <!-- <p class="text-2xl mr-8 text-gray-400 dark:text-gray-500">Commit Message</p> -->

View file

@ -20,7 +20,6 @@ import { UserPermissions } from 'src/app/core/auth/userPermissions';
import { ToppingService } from 'src/app/core/services/topping.service'; import { ToppingService } from 'src/app/core/services/topping.service';
import { copy, transformToTSV } from 'src/app/shared/helpers/copy'; import { copy, transformToTSV } from 'src/app/shared/helpers/copy';
import { RecipeToppingsetComponent } from "./recipe-toppingset/recipe-toppingset.component";
@Component({ @Component({
selector: 'app-recipe-details', selector: 'app-recipe-details',
@ -41,7 +40,6 @@ import { RecipeToppingsetComponent } from "./recipe-toppingset/recipe-toppingset
ConfirmModal, ConfirmModal,
DatePipe, DatePipe,
RecipeListComponent, RecipeListComponent,
RecipeToppingsetComponent,
FormsModule FormsModule
] ]
}) })
@ -94,11 +92,11 @@ export class RecipeDetailsComponent implements OnInit {
toppingSet: ToppingSet[] | null = null; toppingSet: ToppingSet[] | null = null;
submenus: Recipe01[] | null = null; submenus: Recipe01[] | null = null;
ngOnInit() { async ngOnInit() {
this.productCode = this._route.snapshot.params['productCode']; this.productCode = this._route.snapshot.params['productCode'];
this.recipeDetail$ = this._recipeService this.recipeDetail$ = (await this._recipeService
.getRecipeDetail(this.productCode) .getRecipeDetail(this.productCode))
.pipe(first()); .pipe(first());
this.recipeDetail$.subscribe((detail) => { this.recipeDetail$.subscribe((detail) => {
@ -109,7 +107,7 @@ export class RecipeDetailsComponent implements OnInit {
this.recipeOriginalDetail = { ...this.recipeDetailForm.getRawValue() }; this.recipeOriginalDetail = { ...this.recipeDetailForm.getRawValue() };
}); });
this._recipeService.getSubMenus(this._recipeService.getCurrentCountry(), this._recipeService.getCurrentFile(), this.productCode).subscribe((data) => { this._recipeService.getSubMenus(await this._recipeService.getCurrentCountry(), this._recipeService.getCurrentFile(), this.productCode).subscribe((data) => {
console.log('Submenus', data); console.log('Submenus', data);
this.submenus = data; this.submenus = data;
}); });
@ -117,7 +115,7 @@ export class RecipeDetailsComponent implements OnInit {
this.recipeDetailForm.valueChanges.subscribe(this.onRecipeDetailFormChange); this.recipeDetailForm.valueChanges.subscribe(this.onRecipeDetailFormChange);
this._toppingService.getToppingsOfRecipe(this.department, this._recipeService.getCurrentFile(), this.productCode).subscribe((data) => { (await this._toppingService.getToppingsOfRecipe(this.department, this._recipeService.getCurrentFile(), this.productCode)).subscribe((data) => {
this.toppingSet = data; this.toppingSet = data;
// console.log('Toppings', data); // console.log('Toppings', data);
}) })
@ -143,7 +141,7 @@ export class RecipeDetailsComponent implements OnInit {
confirmSave = { confirmSave = {
title: 'The changes detected!', title: 'The changes detected!',
message: 'Do you want to save changes?', message: 'Do you want to save changes?',
confirmCallBack: () => { confirmCallBack: async () => {
console.log('confirm save'); console.log('confirm save');
// get username // get username
@ -177,7 +175,7 @@ export class RecipeDetailsComponent implements OnInit {
// TODO: update value in targeted recipe // TODO: update value in targeted recipe
console.log('to_send', to_send); console.log('to_send', to_send);
this._recipeService.editChanges( this._recipeService.editChanges(
this._recipeService.getCurrentCountry(), await this._recipeService.getCurrentCountry(this.department),
this._recipeService.getCurrentFile(), this._recipeService.getCurrentFile(),
{ {
...to_send, ...to_send,
@ -227,8 +225,9 @@ export class RecipeDetailsComponent implements OnInit {
} }
onRecipeListFormChange(repl: unknown[]) { onRecipeListFormChange(repl: unknown[]) {
// console.log('Recipe List Form Changed', repl); console.log('Recipe List Form Changed', repl);
this.repl = repl as never[]; this.repl = repl[1] as never[];
this.tpl = repl[0] as never[];
this.isValueChanged ||= repl != undefined; this.isValueChanged ||= repl != undefined;
} }

View file

@ -4,7 +4,8 @@
<th class="px-6 py-3">Is Use</th> <th class="px-6 py-3">Is Use</th>
<th class="px-6 py-3">Material ID</th> <th class="px-6 py-3">Material ID</th>
<th class="px-6 py-3">Material Name</th> <th class="px-6 py-3">Material Name</th>
<th class="px-6 py-3">Settings</th> <th class="px-6 py-3">Volume</th>
<th class="">Settings</th>
</tr> </tr>
</thead> </thead>
<tbody <tbody
@ -12,129 +13,140 @@
*ngFor="let mat of recipeListData.controls; let i = index" *ngFor="let mat of recipeListData.controls; let i = index"
> >
<tr <tr
class="bg-white la border-b hover:bg-secondary" class="bg-white border-b hover:bg-secondary max-h-4"
formGroupName="{{ i }}" formGroupName="{{ i }}"
(mousedown)="initHoldEvent()" (mousedown)="initHoldEvent()"
(mouseup)="openRecipeListEditor(i)" (mouseup)="openRecipeListEditor(i)"
> >
<td class="px-6 py-4 font-medium text-gray-900 whitespace-nowrap"> <td class="font-medium text-gray-900 whitespace-nowrap sticky left-0">
<input type="checkbox" class="toggle" formControlName="isUse" /> <input type="checkbox" class="toggle" formControlName="isUse" />
</td> </td>
<td class="px-6 py-4 font-medium text-gray-900 whitespace-nowrap"> <td class="font-medium text-gray-900 whitespace-nowrap sticky">
<input <input
type="text" type="text"
class="input" class="input w-20"
formControlName="materialPathId" formControlName="materialPathId"
(click)="openMaterialList(i)" (click)="openMaterialList(i)"
/> />
</td> </td>
<td class="px-6 py-4 font-medium text-gray-900 whitespace-nowrap"> <td class="font-medium text-gray-900 whitespace-nowrap sticky">
<input type="text" class="input" formControlName="name" /> <input type="text" class="input" formControlName="name" />
</td> </td>
<!-- powder -->
<!-- <div *ngIf="getTypeForRecipeListAtIndex(i)['category'] == 'powder'">
</div> -->
<td <td
class="m-2 px-4 py-4 font-medium text-gray-900 whitespace-nowrap" class="font-medium text-gray-900 whitespace-nowrap"
*ngIf=" *ngIf="
displayByCond(i, 'powderGram', 'not-zero', { compare: undefined }) displayByCond(i, 'powderGram', 'not-zero', { compare: undefined })
" "
> >
<div <div
class="flex justify-center items-center space-x-2 bg-purple-300 rounded-md" class="flex justify-center items-center space-x-2 bg-purple-300 rounded-md p-2"
> >
<p>Volume</p> <p>Volume</p>
<input type="text" class="input w-16" formControlName="powderGram" /> <input type="text" class="bg-transparent w-8" formControlName="powderGram" />
<p>gram</p> <p>gram</p>
</div> </div>
</td> </td>
<td <td
class="m-2 px-4 py-4 font-medium text-gray-900 whitespace-nowrap" class="font-medium text-gray-900 whitespace-nowrap"
*ngIf=" *ngIf="displayByCond(i, 'powderGram', 'zero', { compare: undefined })"
displayByCond(i, 'syrupGram', 'not-zero', { compare: undefined }) &&
getTypeForRecipeListAtIndex(i)['category'] == 'syrup'
"
> >
<div class="flex items-center space-x-2 bg-purple-300 rounded-md"> <div
class="flex items-center space-x-2 bg-purple-300 rounded-md p-2"
*ngIf="
displayByCond(i, 'syrupGram', 'not-zero', { compare: undefined }) &&
getTypeForRecipeListAtIndex(i)['category'] == 'syrup'
"
>
<p>Volume</p> <p>Volume</p>
<input type="text" class="input w-16" formControlName="syrupGram" /> <input type="text" class="bg-transparent w-8" formControlName="syrupGram" />
<p>gram</p> <p>gram</p>
</div> </div>
</td> </td>
<td <td class="font-medium text-gray-900 whitespace-nowrap">
class="m-2 px-4 py-4 space-y-2 font-medium text-gray-900 whitespace-nowrap" <div class="flex flex-row p-2 space-x-3">
> <div class="flex items-center justify-center bg-gray-200">
<div class="flex items-center justify-center space-x-4 bg-gray-200"> <div class="items-center rounded-md" *ngIf="isStringParamExist(i)">
<div <div
class="flex items-center rounded-md" class="flex items-center rounded-md tooltip"
*ngIf="isStringParamExist(i)" [attr.data-tip]="param.pkey"
> *ngFor="let param of getStringParamOfIndex(i)"
<div >
class="flex items-center rounded-md " <!-- <p>&nbsp;</p> -->
*ngFor="let param of getStringParamOfIndex(i)" <p *ngIf="param.pkey == 'notail'">tail</p>
> <input
<!-- <p>&nbsp;</p> --> type="text"
<p *ngIf="param.pkey == 'notail'">tail</p> class="w-8 bg-transparent"
<input placeholder="{{ param.pvalue }}"
type="text" (click)="openStringParamEditor(i)"
class="input input-bordered w-16" />
placeholder="{{ param.pvalue }}" <p *ngIf="param.pkey == 'esp-v2-press-value'">mA</p>
(click)="openStringParamEditor(i)" </div>
/>
<p class="m-4" *ngIf="param.pkey == 'esp-v2-press-value'">
mA
</p>
</div> </div>
</div> </div>
</div> <div
<div class="tooltip flex items-center justify-evenly space-x-2 rounded-md bg-red-200 p-2"
class="flex items-center justify-center space-x-2 rounded-md bg-red-200" data-tip="Hot"
*ngIf="
displayByCond(i, 'waterYield', 'not-zero', { compare: undefined })
"
>
<p>Hot</p>
<input type="text" class="input w-16" formControlName="waterYield" />
<p>ml</p>
</div>
<div
class="flex items-center justify-center space-x-2 rounded-md bg-blue-200"
*ngIf="
displayByCond(i, 'waterCold', 'not-zero', { compare: undefined })
"
>
<p>Cold</p>
<input type="text" class="input w-16" formControlName="waterCold" />
<p>ml</p>
</div>
<div
class="flex items-center justify-center space-x-2 rounded-md bg-green-300"
*ngIf="
displayByCond(i, 'stirTime', 'not-zero', { compare: undefined }) &&
getTypeForRecipeListAtIndex(i)['category'] != 'cup' &&
!isTopping(getTypeForRecipeListAtIndex(i)['id'])
"
>
<p *ngIf="getTypeForRecipeListAtIndex(i)['category'] == 'bean'">
Grinder
</p>
<p *ngIf="getTypeForRecipeListAtIndex(i)['category'] == 'whipper'">
Mix
</p>
<p
*ngIf=" *ngIf="
getTypeForRecipeListAtIndex(i)['category'] == 'others' && displayByCond(i, 'waterYield', 'not-zero', { compare: undefined })
(getTypeForRecipeListAtIndex(i)['id'] == 8001 ||
getTypeForRecipeListAtIndex(i)['id'] == 8002)
" "
> >
Clean <p>Hot</p>
</p>
<input type="text" class="input w-16" formControlName="stirTime" /> <input
<p>sec</p> type="text"
class="w-8 bg-transparent"
formControlName="waterYield"
/>
<p>ml</p>
</div>
<div
class="tooltip flex items-center justify-center space-x-2 rounded-md bg-blue-200 p-2"
data-tip="Cold"
*ngIf="
displayByCond(i, 'waterCold', 'not-zero', { compare: undefined })
"
>
<p>Cold</p>
<input
type="text"
class="w-8 bg-transparent"
formControlName="waterCold"
/>
<p>ml</p>
</div>
<div
class="tooltip flex items-center justify-center space-x-2 rounded-md bg-green-300 p-2"
[attr.data-tip]="
getTooltipForStirTime(getTypeForRecipeListAtIndex(i))
"
*ngIf="
displayByCond(i, 'stirTime', 'not-zero', {
compare: undefined
}) &&
getTypeForRecipeListAtIndex(i)['category'] != 'cup' &&
!isTopping(getTypeForRecipeListAtIndex(i)['id'])
"
>
<p>{{getTooltipForStirTime(getTypeForRecipeListAtIndex(i))}}</p>
<input
type="text"
class="bg-transparent w-8"
formControlName="stirTime"
/>
<p>sec</p>
</div>
</div>
<div class="collapse collapse-open" *ngIf="isTopping(getTypeForRecipeListAtIndex(i)['id'])">
<div class="collapse-title">Topping Settings</div>
<div class="collapse-content">
<app-recipe-topping
[productCode]="productCode"
[index]="getToppingSlotNumber(getTypeForRecipeListAtIndex(i)['id'])"
(toppingSetChange)="onToppingSetChange($event, i)"
></app-recipe-topping>
</div>
</div> </div>
</td> </td>
</tr> </tr>
@ -291,7 +303,11 @@
<summary class="cursor-pointer">Water</summary> <summary class="cursor-pointer">Water</summary>
<div class="flex items-center space-x-2"> <div class="flex items-center space-x-2">
<p class="text-base m-4">Hot (waterYield)</p> <p class="text-base m-4">Hot (waterYield)</p>
<input type="text" class="input w-16" formControlName="waterYield" /> <input
type="text"
class="input w-16"
formControlName="waterYield"
/>
<p class="text-base m-4">ml</p> <p class="text-base m-4">ml</p>
</div> </div>

View file

@ -1,5 +1,5 @@
import { NgFor, NgIf } from '@angular/common'; import { NgFor, NgIf } from '@angular/common';
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; import { Component, EventEmitter, Input, OnInit, Output, ɵNOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR } from '@angular/core';
import { import {
FormArray, FormArray,
FormBuilder, FormBuilder,
@ -29,14 +29,17 @@ import {
StringParam, StringParam,
stringParamsDefinition, stringParamsDefinition,
conditionTests, conditionTests,
inRange inRange,
convertFromInterProductCode
} from 'src/app/shared/helpers/recipe'; } from 'src/app/shared/helpers/recipe';
import { RecipeToppingComponent } from '../recipe-topping/recipe-topping.component';
@Component({ @Component({
selector: 'app-recipe-list', selector: 'app-recipe-list',
templateUrl: './recipe-list.component.html', templateUrl: './recipe-list.component.html',
standalone: true, standalone: true,
imports: [NgIf, NgFor, ReactiveFormsModule, FormsModule], imports: [NgIf, NgFor, ReactiveFormsModule, FormsModule, RecipeToppingComponent]
}) })
export class RecipeListComponent implements OnInit { export class RecipeListComponent implements OnInit {
@Input({ required: true }) productCode!: string; @Input({ required: true }) productCode!: string;
@ -78,6 +81,9 @@ export class RecipeListComponent implements OnInit {
// detailed recipe list // detailed recipe list
showDetailRecipeList: boolean = false; showDetailRecipeList: boolean = false;
// topping list
public toppingList: any[] = [];
constructor( constructor(
private _recipeService: RecipeService, private _recipeService: RecipeService,
private _materialService: MaterialService, private _materialService: MaterialService,
@ -94,9 +100,9 @@ export class RecipeListComponent implements OnInit {
private _recipeListOriginalArray!: RecipeDetailMat[]; private _recipeListOriginalArray!: RecipeDetailMat[];
ngOnInit(): void { async ngOnInit(): Promise<void> {
this._recipeService (await this._recipeService
.getRecipeDetailMat(this.productCode) .getRecipeDetailMat(this.productCode))
.pipe(first()) .pipe(first())
.subscribe(({ result }) => { .subscribe(({ result }) => {
this._recipeListOriginalArray = result; this._recipeListOriginalArray = result;
@ -278,18 +284,23 @@ export class RecipeListComponent implements OnInit {
emitted_res.push(recipeDetailMat); emitted_res.push(recipeDetailMat);
}); });
this.recipeListFormChange.emit(emitted_res as unknown[]); // do another emit
this.recipeListFormChange.emit([this.toppingList, emitted_res] as unknown[]);
} else { } else {
this.recipeListFormChange.emit([]); this.recipeListFormChange.emit([]);
} }
}); });
// TODO: embed this to recipelist // TODO: embed this to recipelist
this._materialService.getMaterialCodes().subscribe((materials) => { (await
// TODO: embed this to recipelist
this._materialService.getMaterialCodes()).subscribe((materials) => {
this.materialList = materials; this.materialList = materials;
console.log("[MatService] get materials", materials.length);
}); });
this._materialService.getFullMaterialDetail().subscribe((materials) => { (await this._materialService.getFullMaterialDetail()).subscribe((materials) => {
this.fullMaterialList = materials; this.fullMaterialList = materials;
this.categoriedMaterial = this.ListCategory(); this.categoriedMaterial = this.ListCategory();
console.log(this.categoriedMaterial); console.log(this.categoriedMaterial);
@ -324,9 +335,17 @@ export class RecipeListComponent implements OnInit {
// console.log("make material list by category", this.makeListCategory()); // console.log("make material list by category", this.makeListCategory());
this.showMaterialSelector = false; this.showMaterialSelector = false;
this.recipeListData.at(i).get('materialPathId')?.setValue(material); this.recipeListData.at(i).get('materialPathId')?.setValue(material);
console.log('set mat ', material, 'to slot', i); // query material for its name
let materialName = this.fullMaterialList!.find(
(mat) => mat.materialId == material
)!.name;
this.recipeListData.at(i).get('name')?.setValue(
materialName
);
console.log('set mat ', material, materialName,'to slot', i);
} }
getTypeForRecipeListAtIndex(i: any) { getTypeForRecipeListAtIndex(i: any) {
@ -372,6 +391,17 @@ export class RecipeListComponent implements OnInit {
this.fullMaterialList!.forEach((mat) => { this.fullMaterialList!.forEach((mat) => {
let category = getMaterialType(mat.materialId); let category = getMaterialType(mat.materialId);
// try again
if(category == 'others'){
// find min
// console.log(Math.floor(mat.materialId / 1000) );
let interCode = Math.floor(mat.materialId / 10000) * 10000;
let originalCode = mat.materialId - (interCode);
// console.log("from",mat.materialId,"interCode", interCode, "originalCode", originalCode);
category = getMaterialType(originalCode);
// console.log("get original category of inter", category);
}
if (Array.isArray(catMap[category])) { if (Array.isArray(catMap[category])) {
catMap[category].push({ catMap[category].push({
@ -391,7 +421,11 @@ export class RecipeListComponent implements OnInit {
isNotExistbyCatagories = (materialId: number) => isNotExistbyCatagories = (materialId: number) =>
getMaterialType(materialId) == 'others'; getMaterialType(materialId) == 'others';
isTopping = (materialId: number) => { return inRange(8111, 8130, materialId); }; isTopping = (materialId: number) => {
return inRange(8111, 8130, convertFromInterProductCode(materialId));
};
getToppingSlotNumber = (mat: number) => convertFromInterProductCode(mat) - 8110;
isStringParamExist = (i: number) => { isStringParamExist = (i: number) => {
let rawStringParam = this.recipeListData.at(i).get('StringParam')?.value; let rawStringParam = this.recipeListData.at(i).get('StringParam')?.value;
@ -481,7 +515,7 @@ export class RecipeListComponent implements OnInit {
if(this.timeoutHandler){ if(this.timeoutHandler){
console.log("timeout get", this.timeout); console.log("timeout get", this.timeout);
if(this.timeout >= 5){ if(this.timeout >= 20){
this.showDetailRecipeList = true; this.showDetailRecipeList = true;
} }
@ -501,4 +535,34 @@ export class RecipeListComponent implements OnInit {
this.recipeListData.value[i][key] this.recipeListData.value[i][key]
); );
} }
getTooltipForStirTime = (cat: {
category: string;
name: any;
id: any;
}) => {
switch (cat.category) {
case 'whipper':
return 'Mix';
case 'bean':
return 'Grinder';
case 'others':
if(inRange(8001, 8002, cat.id)){
return 'Clean';
}
break;
default:
break;
}
return '';
};
onToppingSetChange = (event: any, index: number) => {
// console.log('onToppingSetChange at index', index, "get event", event);
this.toppingList[event[0]] = event[1];
// console.log('onToppingSetChange', this.toppingList);
}
} }

View file

@ -0,0 +1,38 @@
<div [formGroup]="toppingForm">
<div formArrayName="toppingList" *ngFor="let topping of toppingList.controls; let i = index">
<div formGroupName="{{ i }}">
<input type="checkbox" />
<!-- toppingGroup -->
<ng-select
appendTo="body"
[clearable]="false"
[compareWith]="this.compareFunc"
formControlName="groupID"
(close)="getDefaultOfGroup(getGroupIdByIndex(i))"
>
<ng-option
*ngFor="let item of allToppingsDefinitions"
[value]="item.groupId.toString()"
>
<div>{{ item.name }} ({{ item.groupId }})</div>
</ng-option>
</ng-select>
<!-- defaultSelect -->
<ng-select
appendTo="body"
[clearable]="false"
[compareWith]="this.compareFunc"
formControlName="defaultIDSelect"
>
<ng-option
*ngFor="let item of getMembersByGroupId(getGroupIdByIndex(this.index!))"
[value]="item.id.toString()"
>
<div>{{ item.name }} ({{ item.id }})</div>
</ng-option>
</ng-select>
</div>
</div>
</div>

View file

@ -0,0 +1,161 @@
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
import { CommonModule } from '@angular/common';
import { NgSelectModule } from '@ng-select/ng-select';
import {
FormArray,
FormBuilder,
FormsModule,
ReactiveFormsModule,
} from '@angular/forms';
import { RecipeService } from 'src/app/core/services/recipe.service';
import { ToppingService } from 'src/app/core/services/topping.service';
import {
Topping,
ToppingGroup,
ToppingSet,
} from 'src/app/core/models/recipe.model';
import { ActivatedRoute } from '@angular/router';
@Component({
selector: 'app-recipe-topping',
standalone: true,
imports: [CommonModule, NgSelectModule, FormsModule, ReactiveFormsModule],
templateUrl: './recipe-topping.component.html',
})
export class RecipeToppingComponent implements OnInit {
@Input() productCode: string = '';
@Input() index: number | undefined = undefined;
@Output() toppingSetChange = new EventEmitter<unknown[]>();
allToppings: Topping | undefined = undefined;
allToppingsDefinitions:
| { groupId: string; name: string; members: string; default: string }[]
| null = [{ groupId: '0', name: 'none', members: '0', default: '0' }];
allToppingMembersByGroup: {
id: string;
members: { id: string; name: string }[];
}[] = [];
department = this._route.snapshot.paramMap.get('department');
private _toppingSetOriginalArray!: ToppingSet[];
// form
toppingForm = this._formBuilder.group(
{
toppingList: this._formBuilder.array([]),
},
{
updateOn: 'blur',
}
);
get toppingList(): FormArray {
return this.toppingForm.get('toppingList') as FormArray;
}
constructor(
private _formBuilder: FormBuilder,
private _recipeService: RecipeService,
private _toppingService: ToppingService,
private _route: ActivatedRoute
) {}
async ngOnInit(): Promise<void> {
// get topping of this recipe
// initialize toppinglist form
(
await this._toppingService.getToppingsOfRecipe(
await this._recipeService.getCurrentCountry(),
this._recipeService.getCurrentFile(),
this.productCode
)
).subscribe((data) => {
this._toppingSetOriginalArray = data;
// console.log('ToppingSet', data);
// check length of toppingList if in range with given index
if(this.index && data.length >= this.index!){
this.toppingList.push(
this._formBuilder.group({
isUse: data[this.index!].isUse,
groupID: data[this.index!].groupID,
defaultIDSelect: data[this.index!].defaultIDSelect,
ListGroupID: data[this.index!].ListGroupID,
})
);
}
});
// get all topping
(
await this._toppingService.getToppings(
this.department!,
this._recipeService.getCurrentFile()
)
).subscribe((data) => {
this.allToppings = data;
// console.log('allToppings', data);
data.ToppingGroup.forEach((group: ToppingGroup) => {
if (this.allToppingsDefinitions != null) {
// this.allToppingsDefinitions = {};
this.allToppingsDefinitions.push({
groupId: group.groupID,
name: group.name,
members: group.idInGroup,
default: group.idDefault,
});
this.allToppingMembersByGroup.push({
id: group.groupID,
members: this.mapToppingListToMember(group.idInGroup.split(',')),
});
}
});
});
// emit value changes
this.toppingForm.valueChanges.subscribe((value) => {
console.log('emit value', value);
this.toppingSetChange.emit([this.index, this.toppingList.value]);
});
}
compareFunc = (a: any, b: any) => a.toString() === b.toString();
mapToppingListToMember = (mm: string[]) =>
mm.map((m) => {
// find actual topping from toppingList
let actualTopping = this.allToppings!.ToppingList.find((t) => t.id == m);
return {
id: actualTopping!.id,
name: actualTopping?.name == null ? m : actualTopping!.name,
};
});
getMembersByGroupId(groupID: string) {
return this.allToppingMembersByGroup.find((x) => x.id == groupID)?.members;
}
getGroupIdByIndex(i: number) {
return (this.toppingList.value![0] as any).groupID as string;
}
getDefaultOfGroup(groupID: any) {
this.toppingList.controls.forEach((control) => {
if ((control.value as any).groupID == groupID) {
let newDefault = (this.allToppingsDefinitions as any).find(
(x: any) => x.groupId == groupID
)!.default;
control.get('defaultIDSelect')?.setValue(newDefault);
}
})
}
}

View file

@ -1,4 +1,4 @@
<table class="table" [formGroup]="toppingForm"> <!-- <table class="table" [formGroup]="toppingForm">
<thead> <thead>
<tr> <tr>
<th>Slot (Material Id)</th> <th>Slot (Material Id)</th>
@ -48,4 +48,4 @@
<!-- ListGroupID --> <!-- ListGroupID -->
</tr> </tr>
</tbody> </tbody>
</table> </table> -->

View file

@ -1,220 +1,220 @@
import { NgFor } from '@angular/common'; // import { NgFor } from '@angular/common';
import { Component, Input, Output, OnInit, EventEmitter } from '@angular/core'; // import { Component, Input, Output, OnInit, EventEmitter } from '@angular/core';
import { // import {
FormArray, // FormArray,
FormBuilder, // FormBuilder,
FormsModule, // FormsModule,
ReactiveFormsModule, // ReactiveFormsModule,
} from '@angular/forms'; // } from '@angular/forms';
import { forEach, isEqual } from 'lodash'; // import { forEach, isEqual } from 'lodash';
import { // import {
Topping, // Topping,
ToppingGroup, // ToppingGroup,
ToppingList, // ToppingList,
ToppingSet, // ToppingSet,
} from 'src/app/core/models/recipe.model'; // } from 'src/app/core/models/recipe.model';
import { RecipeService } from 'src/app/core/services/recipe.service'; // import { RecipeService } from 'src/app/core/services/recipe.service';
import { ToppingService } from 'src/app/core/services/topping.service'; // import { ToppingService } from 'src/app/core/services/topping.service';
import { NgSelectModule } from '@ng-select/ng-select'; // import { NgSelectModule } from '@ng-select/ng-select';
import { CommonModule } from '@angular/common'; // import { CommonModule } from '@angular/common';
@Component({ // @Component({
selector: 'app-recipe-toppingset', // selector: 'app-recipe-toppingset',
templateUrl: './recipe-toppingset.component.html', // templateUrl: './recipe-toppingset.component.html',
standalone: true, // standalone: true,
imports: [ // imports: [
NgFor, // NgFor,
FormsModule, // FormsModule,
ReactiveFormsModule, // ReactiveFormsModule,
CommonModule, // CommonModule,
NgSelectModule, // NgSelectModule,
], // ],
}) // })
export class RecipeToppingsetComponent implements OnInit { // export class RecipeToppingsetComponent implements OnInit {
@Input() productCode!: string; // @Input() productCode!: string;
@Output() toppingSetChange = new EventEmitter<unknown[]>(); // @Output() toppingSetChange = new EventEmitter<unknown[]>();
allToppings: Topping | undefined = undefined; // allToppings: Topping | undefined = undefined;
allToppingsDefinitions: // allToppingsDefinitions:
| { groupId: string; name: string; members: string; default: string }[] // | { groupId: string; name: string; members: string; default: string }[]
| null = [{ groupId: '0', name: 'none', members: '0', default: '0' }]; // | null = [{ groupId: '0', name: 'none', members: '0', default: '0' }];
allToppingMembersByGroup: { // allToppingMembersByGroup: {
id: string; // id: string;
members: { id: string; name: string }[]; // members: { id: string; name: string }[];
}[] = []; // }[] = [];
private _toppingSetOriginalArray!: ToppingSet[]; // private _toppingSetOriginalArray!: ToppingSet[];
constructor( // constructor(
private _recipeService: RecipeService, // private _recipeService: RecipeService,
private _toppingService: ToppingService, // private _toppingService: ToppingService,
private _formBuilder: FormBuilder // private _formBuilder: FormBuilder
) {} // ) {}
toppingForm = this._formBuilder.group( // toppingForm = this._formBuilder.group(
{ // {
toppingList: this._formBuilder.array([]), // toppingList: this._formBuilder.array([]),
}, // },
{ updateOn: 'blur' } // { updateOn: 'blur' }
); // );
get toppingList(): FormArray { // get toppingList(): FormArray {
return this.toppingForm.get('toppingList') as FormArray; // return this.toppingForm.get('toppingList') as FormArray;
} // }
ngOnInit(): void { // async ngOnInit(): Promise<void> {
this._toppingService // this._toppingService
.getToppingsOfRecipe( // .getToppingsOfRecipe(
this._recipeService.getCurrentCountry(), // await this._recipeService.getCurrentCountry(),
this._recipeService.getCurrentFile(), // this._recipeService.getCurrentFile(),
this.productCode // this.productCode
) // )
.subscribe((data) => { // .subscribe((data) => {
// this.toppingForm.patchValue({toppingList: data}); // // this.toppingForm.patchValue({toppingList: data});
this._toppingSetOriginalArray = data; // this._toppingSetOriginalArray = data;
data.forEach((toppingSet: ToppingSet) => { // data.forEach((toppingSet: ToppingSet) => {
this.toppingList.push( // this.toppingList.push(
this._formBuilder.group({ // this._formBuilder.group({
isUse: toppingSet.isUse, // isUse: toppingSet.isUse,
groupID: toppingSet.groupID, // groupID: toppingSet.groupID,
defaultIDSelect: toppingSet.defaultIDSelect, // defaultIDSelect: toppingSet.defaultIDSelect,
ListGroupID: toppingSet.ListGroupID, // ListGroupID: toppingSet.ListGroupID,
}) // })
); // );
}); // });
// console.log('controls', this.toppingList.controls); // // console.log('controls', this.toppingList.controls);
// this.toppingSetChange.emit(this.toppingSetList); // // this.toppingSetChange.emit(this.toppingSetList);
}); // });
// fetch all toppings : group and list // // fetch all toppings : group and list
this._toppingService // this._toppingService
.getToppings( // .getToppings(
this._recipeService.getCurrentCountry(), // await this._recipeService.getCurrentCountry(),
this._recipeService.getCurrentFile() // this._recipeService.getCurrentFile()
) // )
.subscribe((data) => { // .subscribe((data) => {
this.allToppings = data; // this.allToppings = data;
// console.log('allToppings', data); // // console.log('allToppings', data);
data.ToppingGroup.forEach((group: ToppingGroup) => { // data.ToppingGroup.forEach((group: ToppingGroup) => {
if (this.allToppingsDefinitions != null) { // if (this.allToppingsDefinitions != null) {
// this.allToppingsDefinitions = {}; // // this.allToppingsDefinitions = {};
this.allToppingsDefinitions.push({ // this.allToppingsDefinitions.push({
groupId: group.groupID, // groupId: group.groupID,
name: group.name, // name: group.name,
members: group.idInGroup, // members: group.idInGroup,
default: group.idDefault, // default: group.idDefault,
}); // });
this.allToppingMembersByGroup.push({ // this.allToppingMembersByGroup.push({
id: group.groupID, // id: group.groupID,
members: this.mapToppingListToMember(group.idInGroup.split(',')), // members: this.mapToppingListToMember(group.idInGroup.split(',')),
}); // });
} // }
}); // });
// console.log(this.allToppingsDefinitions); // // console.log(this.allToppingsDefinitions);
// console.log('allToppingMembersByGroup', this.allToppingMembersByGroup); // // console.log('allToppingMembersByGroup', this.allToppingMembersByGroup);
}); // });
this.toppingForm.valueChanges.subscribe((value) => { // this.toppingForm.valueChanges.subscribe((value) => {
//validator // //validator
for (let i = 0; i < value.toppingList!.length; i++) { // for (let i = 0; i < value.toppingList!.length; i++) {
let toppingSet = value.toppingList![i] as any; // let toppingSet = value.toppingList![i] as any;
// handle null case // // handle null case
if (toppingSet.defaultIDSelect == null) { // if (toppingSet.defaultIDSelect == null) {
toppingSet.defaultIDSelect = 0; // toppingSet.defaultIDSelect = 0;
} // }
// handle null case // // handle null case
if (toppingSet.groupID == null) { // if (toppingSet.groupID == null) {
toppingSet.groupID = '0'; // toppingSet.groupID = '0';
} // }
// handle null case // // handle null case
if (!Array.isArray(toppingSet.ListGroupID)) { // if (!Array.isArray(toppingSet.ListGroupID)) {
toppingSet.ListGroupID = [parseInt(toppingSet.groupID), 0, 0, 0]; // toppingSet.ListGroupID = [parseInt(toppingSet.groupID), 0, 0, 0];
} // }
} // }
let isDiff = !isEqual(this._toppingSetOriginalArray, value.toppingList!); // let isDiff = !isEqual(this._toppingSetOriginalArray, value.toppingList!);
if (isDiff) { // if (isDiff) {
let newToppingSetList: any[] = []; // let newToppingSetList: any[] = [];
forEach(value.toppingList!, (toppingSet: any) => { // forEach(value.toppingList!, (toppingSet: any) => {
// transform value // // transform value
toppingSet.defaultIDSelect = parseInt(toppingSet.defaultIDSelect); // toppingSet.defaultIDSelect = parseInt(toppingSet.defaultIDSelect);
newToppingSetList.push(toppingSet); // newToppingSetList.push(toppingSet);
}); // });
// console.log('newToppingList', newToppingSetList); // // console.log('newToppingList', newToppingSetList);
this.toppingSetChange.emit(newToppingSetList as unknown[]); // this.toppingSetChange.emit(newToppingSetList as unknown[]);
} else { // } else {
// console.log('newToppingListNoChange', value.toppingList); // // console.log('newToppingListNoChange', value.toppingList);
this.toppingSetChange.emit([]); // this.toppingSetChange.emit([]);
} // }
}); // });
} // }
// match group id to its name // // match group id to its name
getGroupName(groupID: string) { // getGroupName(groupID: string) {
// check if array // // check if array
if (Array.isArray(this.allToppings!.ToppingGroup)) { // if (Array.isArray(this.allToppings!.ToppingGroup)) {
return (this.allToppings!.ToppingGroup as ToppingGroup[]).find( // return (this.allToppings!.ToppingGroup as ToppingGroup[]).find(
(group) => group.groupID == groupID // (group) => group.groupID == groupID
)?.name; // )?.name;
} else { // } else {
return undefined; // return undefined;
} // }
} // }
openToppingList(i: any) { // openToppingList(i: any) {
console.log('select', i); // console.log('select', i);
} // }
currentGroupId(i: any) { // currentGroupId(i: any) {
console.log('currentGroupId', i); // console.log('currentGroupId', i);
return (this.toppingForm.value.toppingList![i] as any).groupID as string; // return (this.toppingForm.value.toppingList![i] as any).groupID as string;
} // }
getMembersByGroupId(groupID: string) { // getMembersByGroupId(groupID: string) {
return this.allToppingMembersByGroup.find((x) => x.id == groupID)?.members; // return this.allToppingMembersByGroup.find((x) => x.id == groupID)?.members;
} // }
getGroupIdByIndex(i: number) { // getGroupIdByIndex(i: number) {
// console.log("getGroupId",this.toppingList.value![i]) // // console.log("getGroupId",this.toppingList.value![i])
return (this.toppingList.value![i] as any).groupID as string; // return (this.toppingList.value![i] as any).groupID as string;
} // }
mapToppingListToMember = (mm: string[]) => // mapToppingListToMember = (mm: string[]) =>
mm.map((m) => { // mm.map((m) => {
// find actual topping from toppingList // // find actual topping from toppingList
let actualTopping = this.allToppings!.ToppingList.find((t) => t.id == m); // let actualTopping = this.allToppings!.ToppingList.find((t) => t.id == m);
return { // return {
id: actualTopping!.id, // id: actualTopping!.id,
name: actualTopping?.name == null ? m : actualTopping!.name, // name: actualTopping?.name == null ? m : actualTopping!.name,
}; // };
}); // });
getDefaultOfGroup(groupID: any) { // getDefaultOfGroup(groupID: any) {
this.toppingList.controls.forEach((control) => { // this.toppingList.controls.forEach((control) => {
if ((control.value as any).groupID == groupID) { // if ((control.value as any).groupID == groupID) {
let newDefault = this.allToppingsDefinitions!.find( // let newDefault = this.allToppingsDefinitions!.find(
(x) => x.groupId == groupID // (x) => x.groupId == groupID
)!.default; // )!.default;
// set new defaultid // // set new defaultid
control.get('defaultIDSelect')?.setValue(newDefault); // control.get('defaultIDSelect')?.setValue(newDefault);
} // }
}); // });
} // }
compareFunc = (a: any, b: any) => a.toString() === b.toString(); // compareFunc = (a: any, b: any) => a.toString() === b.toString();
} // }

View file

@ -1,4 +1,5 @@
import { import {
AfterViewInit,
Component, Component,
ElementRef, ElementRef,
OnDestroy, OnDestroy,
@ -24,7 +25,7 @@ import {
tap, tap,
} from 'rxjs'; } from 'rxjs';
import * as lodash from 'lodash'; import * as lodash from 'lodash';
import { ActivatedRoute, RouterLink } from '@angular/router'; import { ActivatedRoute, Router, RouterLink } from '@angular/router';
import { NgSelectModule } from '@ng-select/ng-select'; import { NgSelectModule } from '@ng-select/ng-select';
import { FormsModule } from '@angular/forms'; import { FormsModule } from '@angular/forms';
import { MaterialService } from 'src/app/core/services/material.service'; import { MaterialService } from 'src/app/core/services/material.service';
@ -32,6 +33,8 @@ import { UserService } from 'src/app/core/services/user.service';
import { UserPermissions } from 'src/app/core/auth/userPermissions'; import { UserPermissions } from 'src/app/core/auth/userPermissions';
import { ToppingService } from 'src/app/core/services/topping.service'; import { ToppingService } from 'src/app/core/services/topping.service';
import { copy, transformToTSV } from 'src/app/shared/helpers/copy'; import { copy, transformToTSV } from 'src/app/shared/helpers/copy';
import { getCountryMapSwitcher } from 'src/app/shared/helpers/recipe';
import { AsyncStorage } from 'src/app/shared/helpers/asyncStorage';
@Component({ @Component({
selector: 'app-recipes', selector: 'app-recipes',
@ -46,7 +49,7 @@ import { copy, transformToTSV } from 'src/app/shared/helpers/copy';
], ],
templateUrl: './recipes.component.html', templateUrl: './recipes.component.html',
}) })
export class RecipesComponent implements OnInit, OnDestroy { export class RecipesComponent implements OnInit, OnDestroy, AfterViewInit {
recipesDashboard$!: Observable<RecipesDashboard>; recipesDashboard$!: Observable<RecipesDashboard>;
recipeOverviewList!: RecipeOverview[]; recipeOverviewList!: RecipeOverview[];
selectMaterialFilter: number[] | null = null; selectMaterialFilter: number[] | null = null;
@ -89,12 +92,12 @@ export class RecipesComponent implements OnInit, OnDestroy {
department: string = this.route.parent!.snapshot.params['department']; department: string = this.route.parent!.snapshot.params['department'];
copyList: any[] = []; copyList: any[] = [];
@ViewChild('table', { static: false }) set content(table: ElementRef) { currentVersion: number | undefined = undefined;
// expose element ref for other fn
@ViewChild('table', { static: false }) set content(table: ElementRef) {
table.nativeElement.addEventListener( table.nativeElement.addEventListener(
'scroll', 'scroll',
() => { async () => {
if (this.isHasMore === false) { if (this.isHasMore === false) {
return; return;
} }
@ -103,15 +106,15 @@ export class RecipesComponent implements OnInit, OnDestroy {
const isBottom = scrollTop + clientHeight >= scrollHeight - 10; const isBottom = scrollTop + clientHeight >= scrollHeight - 10;
if (isBottom && !this.isLoadMore) { if (isBottom && !this.isLoadMore) {
this.isLoadMore = true; this.isLoadMore = true;
this._recipeService (await this._recipeService
.getRecipeOverview({ .getRecipeOverview({
offset: this.offset, offset: this.offset,
take: this.take, take: this.take,
search: this.oldSearchStr, search: this.oldSearchStr,
filename: this._recipeService.getCurrentFile(), filename: this._recipeService.getCurrentFile(),
country: this._recipeService.getCurrentCountry(), country: await this._recipeService.getCurrentCountry(this.department),
materialIds: this.selectMaterialFilter || [], materialIds: this.selectMaterialFilter || [],
}) }))
.subscribe(({ result, hasMore, totalCount }) => { .subscribe(({ result, hasMore, totalCount }) => {
if (this.recipeOverviewList) { if (this.recipeOverviewList) {
this.recipeOverviewList = this.recipeOverviewList =
@ -134,26 +137,28 @@ export class RecipesComponent implements OnInit, OnDestroy {
private _materialService: MaterialService, private _materialService: MaterialService,
private _toppingService: ToppingService, private _toppingService: ToppingService,
private route: ActivatedRoute, private route: ActivatedRoute,
private _userService: UserService private _userService: UserService,
private _router: Router
) {} ) {}
ngOnInit(): void { async ngOnInit(): Promise<void> {
console.log('Trigger onInit where department = ', this.department);
this.recipesDashboard$ = this._recipeService this.recipesDashboard$ = this._recipeService
.getRecipesDashboard({ .getRecipesDashboard({
filename: this._recipeService.getCurrentFile(), filename: this._recipeService.getCurrentFile(),
country: this._recipeService.getCurrentCountry(), country: await this._recipeService.getCurrentCountry(this.department!),
}) })
.pipe( .pipe(
finalize(() => { finalize(async () => {
this._recipeService (await this._recipeService
.getRecipeOverview({ .getRecipeOverview({
offset: this.offset, offset: this.offset,
take: this.take, take: this.take,
search: this.oldSearchStr, search: this.oldSearchStr,
filename: this._recipeService.getCurrentFile(), filename: this._recipeService.getCurrentFile(),
country: this._recipeService.getCurrentCountry(), country: await this._recipeService.getCurrentCountry(this.department!),
materialIds: this.selectMaterialFilter || [], materialIds: this.selectMaterialFilter || [],
}) }))
.subscribe(({ result, hasMore, totalCount }) => { .subscribe(({ result, hasMore, totalCount }) => {
this.recipeOverviewList = result; this.recipeOverviewList = result;
this.offset += 10; this.offset += 10;
@ -163,9 +168,34 @@ export class RecipesComponent implements OnInit, OnDestroy {
}) })
); );
// FIXME: Lag assigned
this.recipesDashboard$.subscribe((data) => {
this.currentVersion = data.configNumber;
console.log('current version', this.currentVersion);
});
console.log('ngAfterViewInit::department', this.department);
console.log('::CurrentFile', this._recipeService.getCurrentFile());
(await this._materialService
.getFullMaterialDetail(
this.department,
this._recipeService.getCurrentFile()
))
.subscribe((mat) => {
this.materialDetail = mat;
console.log(this.materialDetail?.length, "[0]=", mat?.at(0), "current country", this._recipeService.getCurrentCountry(), "currentFile", this._recipeService.getCurrentFile());
// check material detail
console.log('first material', this.materialDetail![0]);
});
// end of FIXME
this._recipeService this._recipeService
.getSavedTmp( .getSavedTmp(
this._recipeService.getCurrentCountry(), await this._recipeService.getCurrentCountry(this.department),
this._recipeService.getCurrentFile() this._recipeService.getCurrentFile()
) )
.subscribe({ .subscribe({
@ -195,8 +225,10 @@ export class RecipesComponent implements OnInit, OnDestroy {
}); });
// TODO: get all materials; MaterialSetting + MaterialCode // TODO: get all materials; MaterialSetting + MaterialCode
this._materialService (await
.getMaterialCodes() // TODO: get all materials; MaterialSetting + MaterialCode
this._materialService
.getMaterialCodes())
.pipe( .pipe(
map((mat) => map((mat) =>
mat.map((m) => ({ mat.map((m) => ({
@ -209,18 +241,8 @@ export class RecipesComponent implements OnInit, OnDestroy {
this.materialList = materials; this.materialList = materials;
}); });
this._materialService (await this._toppingService
.getFullMaterialDetail( .getToppings(this.department, this._recipeService.getCurrentFile()))
this.department,
this._recipeService.getCurrentFile()
)
.subscribe((mat) => {
this.materialDetail = mat;
console.log(this.materialDetail?.length);
});
this._toppingService
.getToppings(this.department, this._recipeService.getCurrentFile())
.subscribe((tp) => { .subscribe((tp) => {
this.toppings = { this.toppings = {
toppingGroup: tp.ToppingGroup, toppingGroup: tp.ToppingGroup,
@ -232,24 +254,35 @@ export class RecipesComponent implements OnInit, OnDestroy {
this.initRecipeSelection(); this.initRecipeSelection();
} }
ngAfterViewInit(): void {
console.log('After view on init trigger');
}
setSearch(event: Event) { setSearch(event: Event) {
console.log((event.target as HTMLInputElement).value); console.log((event.target as HTMLInputElement).value);
this.searchStr = (event.target as HTMLInputElement).value; this.searchStr = (event.target as HTMLInputElement).value;
} }
search(event: Event) { async search(event: Event) {
// country
let country = await this._recipeService.getCurrentCountry(this.department).then(
(country) => country
);
this.offset = 0; this.offset = 0;
this.isLoadMore = true; this.isLoadMore = true;
this.oldSearchStr = this.searchStr; this.oldSearchStr = this.searchStr;
this._recipeService (await this._recipeService
.getRecipeOverview({ .getRecipeOverview({
offset: this.offset, offset: this.offset,
take: this.take, take: this.take,
search: this.oldSearchStr, search: this.oldSearchStr,
filename: this._recipeService.getCurrentFile(), filename: this._recipeService.getCurrentFile(),
country: this._recipeService.getCurrentCountry(), country: country,
materialIds: this.selectMaterialFilter || [], materialIds: this.selectMaterialFilter || [],
}) }))
.subscribe(({ result, hasMore, totalCount }) => { .subscribe(({ result, hasMore, totalCount }) => {
this.recipeOverviewList = result; this.recipeOverviewList = result;
this.offset += 10; this.offset += 10;
@ -397,40 +430,63 @@ export class RecipesComponent implements OnInit, OnDestroy {
); );
} }
countrySelected(country: string) { async countrySelected(country: string) {
this.selectedCountry = country; this.selectedCountry = country;
this.isCountrySelected = true; this.isCountrySelected = true;
localStorage.setItem('currentRecipeCountry', country); // localStorage.setItem('currentRecipeCountry', country);
await AsyncStorage.setItem('currentRecipeCountry', country);
// force reload, will fix this later
void this._router
.navigate([`/${getCountryMapSwitcher(country)}/recipes`]);
} }
loadRecipe(recipeFileName: string) { async loadRecipe(recipeFileName: string) {
// clear all recipes // clear all recipes
this.offset = 0; this.offset = 0;
this.isHasMore = true; this.isHasMore = true;
this.isLoadMore = true; this.isLoadMore = true;
this.oldSearchStr = ''; this.oldSearchStr = '';
localStorage.setItem('currentRecipeFile', recipeFileName); // localStorage.setItem('currentRecipeFile', recipeFileName);
this.recipesDashboard$ = this._recipeService.getRecipesDashboard({ await AsyncStorage.setItem('currentRecipeFile', recipeFileName);
filename: recipeFileName,
country: this.selectedCountry!,
});
this._recipeService
.getRecipeOverview({
offset: this.offset,
take: this.take, console.log('loadRecipe', recipeFileName, "currentCountry", this.department, "selectedCountry", this.selectedCountry);
search: this.oldSearchStr,
filename: recipeFileName, // clear all menus
country: this.selectedCountry!, this.recipeOverviewList = [];
materialIds: this.selectMaterialFilter || [],
}) // this.recipesDashboard$ = this._recipeService.getRecipesDashboard({
.subscribe(({ result, hasMore, totalCount }) => { // filename: recipeFileName,
this.recipeOverviewList = result; // country: this.selectedCountry!,
this.offset += 10; // });
this.isHasMore = hasMore;
this.isLoadMore = false; // this.recipesDashboard$.subscribe((data) => {
}); // this.currentVersion = data.configNumber;
// console.log('current version', this.currentVersion);
// });
// this._recipeService
// .getRecipeOverview({
// offset: this.offset,
// take: this.take,
// search: this.oldSearchStr,
// filename: recipeFileName,
// country: this.selectedCountry!,
// materialIds: this.selectMaterialFilter || [],
// })
// .subscribe(({ result, hasMore, totalCount }) => {
// this.recipeOverviewList = result;
// this.offset += 10;
// this.isHasMore = hasMore;
// this.isLoadMore = false;
// });
window.location.reload();
} }
// end of Recipe Version selection // end of Recipe Version selection
@ -438,7 +494,9 @@ export class RecipesComponent implements OnInit, OnDestroy {
openJsonTab() { openJsonTab() {
window.open( window.open(
environment.api + environment.api +
`/recipes/${this._recipeService.getCurrentCountry()}/${this._recipeService.getCurrentFile()}/json`, `/recipes/${this._recipeService.getCurrentCountry(
this.department
)}/${this._recipeService.getCurrentFile()}/json`,
'_blank' '_blank'
); );
} }
@ -448,7 +506,7 @@ export class RecipesComponent implements OnInit, OnDestroy {
this.saveTab = true; this.saveTab = true;
} }
loadSavedFile(file_commit: any) { async loadSavedFile(file_commit: any) {
this.showSaveNoti = false; this.showSaveNoti = false;
this.saveTab = false; this.saveTab = false;
console.log('loadSavedFile', file_commit, this.department); console.log('loadSavedFile', file_commit, this.department);
@ -472,7 +530,7 @@ export class RecipesComponent implements OnInit, OnDestroy {
console.log(file_commit.Change_file.split('/')[2]); console.log(file_commit.Change_file.split('/')[2]);
this._recipeService (await this._recipeService
.getRecipeOverview({ .getRecipeOverview({
offset: this.offset, offset: this.offset,
take: this.take, take: this.take,
@ -480,7 +538,7 @@ export class RecipesComponent implements OnInit, OnDestroy {
filename: file_commit.Change_file.split('/')[2], filename: file_commit.Change_file.split('/')[2],
country: country, country: country,
materialIds: this.selectMaterialFilter || [], materialIds: this.selectMaterialFilter || [],
}) }))
.subscribe(({ result, hasMore, totalCount }) => { .subscribe(({ result, hasMore, totalCount }) => {
console.log('loadSavedFile', result); console.log('loadSavedFile', result);
this._recipeService.setCurrentFile( this._recipeService.setCurrentFile(
@ -503,26 +561,22 @@ export class RecipesComponent implements OnInit, OnDestroy {
item.name.toLowerCase().includes(term.toLowerCase()) || item.name.toLowerCase().includes(term.toLowerCase()) ||
item.materialId.toString().includes(term); item.materialId.toString().includes(term);
addToCopyList(data: any) {
addToCopyList(data: any){ if (this.copyList.includes(data)) {
if(this.copyList.includes(data)){
let index = this.copyList.indexOf(data); let index = this.copyList.indexOf(data);
this.copyList.splice(index, 1); this.copyList.splice(index, 1);
} else { } else {
this.copyList = [...this.copyList, data]; this.copyList = [...this.copyList, data];
} }
} }
async copyToTsv(data: any) {
async copyToTsv(data: any){ await copy(transformToTSV(data))
.then((value) => {
await copy(transformToTSV(data)).then( (value) => {
console.log('copyToTsv', value); console.log('copyToTsv', value);
}).catch( (err) => { })
.catch((err) => {
console.log('copyToTsvErr', err); console.log('copyToTsvErr', err);
}); });
} }
} }

View file

@ -0,0 +1,14 @@
export class AsyncStorage {
static async getItem<T>(key: string) {
return new Promise<T>((resolve) => {
resolve(localStorage.getItem(key) as T);
});
}
static async setItem(key: string, value: string) {
return new Promise<void>((resolve) => {
localStorage.setItem(key, value);
resolve();
});
}
}

View file

@ -1,3 +1,5 @@
import { Tuple } from "./tuple";
var rangeMaterialMapping: { [key: string]: (id: number) => boolean } = { var rangeMaterialMapping: { [key: string]: (id: number) => boolean } = {
soda: (id: number) => id == 1031, soda: (id: number) => id == 1031,
water: (id: number) => id == 1, water: (id: number) => id == 1,
@ -46,6 +48,14 @@ export function isNonMaterial(materialId: number) {
); );
} }
// Inter mode checker
export function convertFromInterProductCode(materialId: number) {
let interPrefix = Math.floor(materialId / 10000) * 10000;
let interId = materialId - interPrefix;
return interId;
}
// StringParam // StringParam
export class StringParam { export class StringParam {
@ -92,5 +102,24 @@ export var stringParamsDefinition: { [key: string]: string } = {
export var conditionTests: { [key: string]: (arg: any) => boolean } = { export var conditionTests: { [key: string]: (arg: any) => boolean } = {
'not-zero': (arg: any) => arg != 0, 'not-zero': (arg: any) => arg != 0,
'zero': (arg: any) => arg == 0,
'false-if-another-exist': (arg: any) => arg[1] != undefined 'false-if-another-exist': (arg: any) => arg[1] != undefined
} }
export var countryMap: Tuple<string, string>[] = [
new Tuple<string, string>('tha', 'Thailand'),
new Tuple<string, string>('mys', 'Malaysia'),
new Tuple<string, string>('aus', 'Australia'),
];
export function getCountryMapSwitcher(param: string) {
console.log("param = ", param);
for (const country of countryMap) {
if(country.first == param || country.second == param){
return country.switchGet(param);
}
}
}

View file

@ -0,0 +1,15 @@
export class Tuple<T, U> {
constructor(public first: T, public second: U) {}
public get(): [T, U] {
return [this.first, this.second];
}
public switchGet(elem: any): any{
if(elem == this.first){
return this.second;
} else {
return this.first;
}
}
}

View file

@ -18,18 +18,25 @@ import (
) )
type RecipeWithTimeStamps struct { type RecipeWithTimeStamps struct {
Recipe models.Recipe Recipe map[string]*models.Recipe
TimeStamps int64 TimeStamps int64
} }
type Data struct { type Data struct {
CurrentFile string CurrentFile map[string]string
CurrentCountryID string CurrentCountryID map[string]string
AllRecipeFiles map[string][]helpers.RecipePath DefaultCountryMap []DefaultByCountry
currentRecipe *models.Recipe AllRecipeFiles map[string][]helpers.RecipePath
recipeMap map[string]RecipeWithTimeStamps currentRecipe map[string]*models.Recipe
Countries []helpers.CountryName recipeMap map[string]RecipeWithTimeStamps
taoLogger *logger.TaoLogger Countries []helpers.CountryName
taoLogger *logger.TaoLogger
}
type DefaultByCountry struct {
CountryShortName string
CountryLongName string
DefaultFileVersion int
} }
var ( var (
@ -51,99 +58,165 @@ func NewData(taoLogger *logger.TaoLogger) *Data {
allRecipeFiles := helpers.ScanRecipeFiles(countries) allRecipeFiles := helpers.ScanRecipeFiles(countries)
defaultFile := "coffeethai02_600.json" defaultFile := "coffeethai02_600.json"
defaultCountry := "tha"
// TODO: read 'version' file // TODO: read 'version' file by country
versionPath := path.Join("cofffeemachineConfig", defaultCountry, "version")
taoLogger.Log.Debug("version", zap.Any("version path", versionPath))
// versionFile, err := os.Open(versionPath) // versionPath := path.Join("cofffeemachineConfig", defaultCountry, "version")
content, err := os.ReadFile(versionPath) // taoLogger.Log.Debug("version", zap.Any("version path", versionPath))
if err != nil { // // versionFile, err := os.Open(versionPath)
taoLogger.Log.Debug("Error when open version file", zap.Error(err)) // content, err := os.ReadFile(versionPath)
}
initVersion := string(content) // if err != nil {
// taoLogger.Log.Debug("Error when open version file", zap.Error(err))
// }
// read latest version // initVersion := string(content)
// set latest to default version
latest_version, err := strconv.Atoi(initVersion)
if err != nil { // // read latest version
latest_version = 600 // // set latest to default version
} // latest_version, err := strconv.Atoi(initVersion)
for _, v := range allRecipeFiles[defaultCountry] { // if err != nil {
// latest_version = 600
// }
// extract filename as version defaultForEachCountry := []DefaultByCountry{}
current_version_iter, err := strconv.Atoi(strings.Split(strings.Split(v.Name, "_")[1], ".")[0])
for _, elem := range countries {
// generate default of all countries
currentVersionPath := path.Join("cofffeemachineConfig", elem.CountryID, "version")
// this is default version for each country
content, err := os.ReadFile(currentVersionPath)
if err != nil { if err != nil {
continue taoLogger.Log.Debug("Error when open version file", zap.Error(err))
} }
if current_version_iter == latest_version { initVersion := string(content)
// taoLogger.Log.Debug("current_version_iter", zap.Any("current_version_iter", current_version_iter))
// set latest // read latest version
latest_version = current_version_iter latest_version, _ := strconv.Atoi(initVersion)
defaultFile = v.Name defaultForEachCountry = append(defaultForEachCountry, DefaultByCountry{CountryShortName: elem.CountryID, CountryLongName: elem.CountryName, DefaultFileVersion: latest_version})
break }
currentFileMap := make(map[string]string)
CurrentCountryIDMap := make(map[string]string)
currentDefaultFileForEachCountry := make(map[string]*models.Recipe)
// all default versions as string
versionsString := ""
// loop default for each country
for _, v := range defaultForEachCountry {
for _, v2 := range allRecipeFiles[v.CountryShortName] {
// extract filename as version
current_version_iter, err := strconv.Atoi(strings.Split(strings.Split(v2.Name, "_")[1], ".")[0])
if err != nil {
continue
}
if current_version_iter == v.DefaultFileVersion {
currentFileMap[v.CountryShortName] = v2.Name
CurrentCountryIDMap[v.CountryShortName] = v.CountryLongName
versionsString = versionsString + v.CountryShortName + ":" + strconv.Itoa(current_version_iter) + ","
// do read default
defaultRecipe, err := helpers.ReadRecipeFile(v.CountryShortName, v2.Name)
if err != nil {
log.Panic("Error when read default recipe file for each country:", v.CountryShortName, err)
}
currentDefaultFileForEachCountry[v.CountryShortName] = defaultRecipe
break
}
} }
} }
taoLogger.Log.Debug("defaultFile", zap.Any("defaultFile", defaultFile), zap.Any("latest_version", latest_version)) // for _, v := range allRecipeFiles[defaultCountry] {
defaultRecipe, err := helpers.ReadRecipeFile(defaultCountry, defaultFile) // // extract filename as version
// current_version_iter, err := strconv.Atoi(strings.Split(strings.Split(v.Name, "_")[1], ".")[0])
if err != nil { // if err != nil {
log.Panic("Error when read default recipe file:", err) // continue
} // }
// if current_version_iter == latest_version {
// // taoLogger.Log.Debug("current_version_iter", zap.Any("current_version_iter", current_version_iter))
// // set latest
// latest_version = current_version_iter
// defaultFile = v.Name
// break
// }
// }
// FIXME: default file bug. do assign each default recipe model to each country
// taoLogger.Log.Debug("defaultFile", zap.Any("defaultFile", defaultFile), zap.Any("latest_version", versionsString))
// defaultRecipe, err := helpers.ReadRecipeFile(defaultCountry, defaultFile)
// if err != nil {
// log.Panic("Error when read default recipe file:", err)
// }
return &Data{ return &Data{
CurrentFile: defaultFile, CurrentFile: currentFileMap,
CurrentCountryID: defaultCountry, CurrentCountryID: CurrentCountryIDMap,
AllRecipeFiles: allRecipeFiles, AllRecipeFiles: allRecipeFiles,
currentRecipe: defaultRecipe, currentRecipe: currentDefaultFileForEachCountry,
recipeMap: map[string]RecipeWithTimeStamps{ recipeMap: map[string]RecipeWithTimeStamps{
defaultFile: { defaultFile: {
Recipe: *defaultRecipe, Recipe: currentDefaultFileForEachCountry,
TimeStamps: time.Now().Unix(), TimeStamps: time.Now().Unix(),
}, },
}, },
Countries: countries, Countries: countries,
taoLogger: taoLogger, taoLogger: taoLogger,
DefaultCountryMap: defaultForEachCountry,
} }
} }
func (d *Data) GetRecipe(countryID, filename string) *models.Recipe { func (d *Data) GetRecipe(countryID, filename string) *models.Recipe {
d.taoLogger.Log.Debug("invoke GetRecipe", zap.String("countryID", countryID), zap.String("filename", filename))
if countryID == "" { if countryID == "" {
return d.currentRecipe return d.currentRecipe["tha"]
} }
if filename == "" || filename == d.CurrentFile { if filename == "" || filename == d.CurrentFile[countryID] {
return d.currentRecipe return d.currentRecipe[countryID]
} }
if recipe, ok := d.recipeMap[filename]; ok { if recipe, ok := d.recipeMap[filename]; ok {
d.CurrentFile = filename d.CurrentFile[countryID] = filename
d.CurrentCountryID = countryID // d.CurrentCountryID[countryID] = countryID
return &recipe.Recipe return recipe.Recipe[countryID]
} }
// change current version and read new recipe // change current version and read new recipe
d.CurrentFile = filename
if filename == "default" {
filename = d.CurrentFile[countryID]
}
// d.CurrentFile[countryID] = filename
d.taoLogger.Log.Debug("GetRecipe", zap.String("filename", filename), zap.String("countryID", countryID)) d.taoLogger.Log.Debug("GetRecipe", zap.String("filename", filename), zap.String("countryID", countryID))
d.CurrentCountryID = countryID // d.CurrentCountryID[countryID] = countryID
recipe, err := helpers.ReadRecipeFile(countryID, filename) recipe, err := helpers.ReadRecipeFile(countryID, filename)
if err != nil { if err != nil {
d.taoLogger.Log.Error("Error when read recipe file, Return default recipe", zap.Error(err)) d.taoLogger.Log.Error("GetRecipe: Error when read recipe file, Return default recipe", zap.Error(err))
return d.currentRecipe return d.currentRecipe[countryID]
} }
d.currentRecipe = recipe d.currentRecipe[countryID] = recipe
// save to map // save to map
if len(d.recipeMap) > 5 { // limit keep in memory 5 version if len(d.recipeMap) > 5 { // limit keep in memory 5 version
@ -160,47 +233,73 @@ func (d *Data) GetRecipe(countryID, filename string) *models.Recipe {
} }
d.recipeMap[filename] = RecipeWithTimeStamps{ d.recipeMap[filename] = RecipeWithTimeStamps{
Recipe: *d.currentRecipe, Recipe: d.currentRecipe,
TimeStamps: time.Now().Unix(), TimeStamps: time.Now().Unix(),
} }
return d.currentRecipe return d.currentRecipe[countryID]
} }
func (d *Data) GetRecipe01() []models.Recipe01 { // func (d *Data) GetRecipe01() []models.Recipe01 {
return d.currentRecipe.Recipe01 // return d.currentRecipe.Recipe01
} // }
func (d *Data) GetCurrentRecipe() *models.Recipe { // func (d *Data) GetCurrentRecipe() *models.Recipe {
return d.currentRecipe // return d.currentRecipe
} // }
func (d *Data) GetRecipe01ByProductCode(filename, countryID, productCode string) (models.Recipe01, error) { func (d *Data) GetRecipe01ByProductCode(filename, countryID, productCode string) (models.Recipe01, error) {
if !strings.Contains(filename, "tmp") { // try convert
if filename == "" || filename == d.CurrentFile { if len(countryID) != 3 {
fmt.Println("GetRecipe01ByProductCode.ReadCurrent", filename, d.CurrentFile) for k, v := range d.CurrentCountryID {
for _, v := range d.currentRecipe.Recipe01 { fmt.Println("GetRecipe01ByProductCode.Iterate", k, v, v == countryID)
if v.ProductCode == productCode { if v == countryID {
return v, nil countryID = k
} break
}
} else if recipe, ok := d.recipeMap[filename]; ok {
fmt.Println("GetRecipe01ByProductCode.ReadMap", filename, d.CurrentFile)
for _, v := range recipe.Recipe.Recipe01 {
if v.ProductCode == productCode {
return v, nil
}
} }
} }
} }
fmt.Println("GetRecipe01ByProductCode", filename, countryID, productCode)
d.CurrentFile = filename if !strings.Contains(filename, "tmp") {
d.CurrentCountryID = countryID if filename == "" || filename == d.CurrentFile[countryID] {
// , d.CurrentFile, countryID, "result by country id", len(d.currentRecipe[countryID].Recipe01)
fmt.Println("GetRecipe01ByProductCode.ReadCurrent::filename", filename)
fmt.Println("GetRecipe01ByProductCode.ReadCurrent::countryID", countryID)
fmt.Println("GetRecipe01ByProductCode.ReadCurrent::CurrentFile", d.CurrentFile)
fmt.Println("GetRecipe01ByProductCode.ReadCurrent::CurrentCountryID", d.CurrentCountryID)
for _, v := range d.currentRecipe[countryID].Recipe01 {
if v.ProductCode == productCode {
return v, nil
}
}
fmt.Println("No result in current recipe", countryID)
} else if recipe, ok := d.recipeMap[filename]; ok {
fmt.Println("GetRecipe01ByProductCode.ReadMap", filename, d.CurrentFile, recipe.Recipe[countryID], "countryID=", countryID)
for _, v := range recipe.Recipe[countryID].Recipe01 {
if v.ProductCode == productCode {
d.taoLogger.Log.Debug("GetRecipe01ByProductCode.getSuccess", zap.Any("fromFile", filename), zap.Any("whereSource", d.recipeMap))
return v, nil
}
}
d.taoLogger.Log.Debug("GetRecipe01ByProductCode.getFail", zap.Any("fromFile", filename), zap.Any("whereSource", d.recipeMap))
}
}
d.taoLogger.Log.Debug("GetRecipe01ByProductCode", zap.Any("filename", filename), zap.Any("countryID", countryID), zap.Any("productCode", productCode))
if filename == "default" {
filename = d.CurrentFile[countryID]
}
// d.CurrentFile[countryID] = filename
// d.CurrentCountryID[countryID] = countryID
for _, v := range countries { for _, v := range countries {
if v.CountryName == countryID { if v.CountryName == countryID {
d.CurrentCountryID = v.CountryID // d.CurrentCountryID[countryID] = v.CountryID
countryID = v.CountryID countryID = v.CountryID
break break
} }
@ -209,8 +308,8 @@ func (d *Data) GetRecipe01ByProductCode(filename, countryID, productCode string)
recipe, err := helpers.ReadRecipeFile(countryID, filename) recipe, err := helpers.ReadRecipeFile(countryID, filename)
if err != nil { if err != nil {
d.taoLogger.Log.Error("Error when read recipe file, Return default recipe", zap.Error(err)) d.taoLogger.Log.Error("GetRecipe01ByProductCode: Error when read recipe file, Return default recipe", zap.Error(err))
for _, v := range d.currentRecipe.Recipe01 { for _, v := range d.currentRecipe[countryID].Recipe01 {
if v.ProductCode == productCode { if v.ProductCode == productCode {
return v, nil return v, nil
} }
@ -219,7 +318,7 @@ func (d *Data) GetRecipe01ByProductCode(filename, countryID, productCode string)
d.taoLogger.Log.Debug("GetRecipe01ByProductCode", zap.Any("productCode", productCode), zap.Any("version", recipe.MachineSetting.ConfigNumber)) d.taoLogger.Log.Debug("GetRecipe01ByProductCode", zap.Any("productCode", productCode), zap.Any("version", recipe.MachineSetting.ConfigNumber))
d.currentRecipe = recipe d.currentRecipe[countryID] = recipe
// save to map // save to map
if len(d.recipeMap) > 5 { // limit keep in memory 5 version if len(d.recipeMap) > 5 { // limit keep in memory 5 version
@ -236,11 +335,11 @@ func (d *Data) GetRecipe01ByProductCode(filename, countryID, productCode string)
} }
d.recipeMap[filename] = RecipeWithTimeStamps{ d.recipeMap[filename] = RecipeWithTimeStamps{
Recipe: *d.currentRecipe, Recipe: d.currentRecipe,
TimeStamps: time.Now().Unix(), TimeStamps: time.Now().Unix(),
} }
for _, v := range d.currentRecipe.Recipe01 { for _, v := range d.currentRecipe[countryID].Recipe01 {
if v.ProductCode == productCode { if v.ProductCode == productCode {
// d.taoLogger.Log.Debug("GetRecipe01ByProductCode", zap.Any("productCode", productCode), zap.Any("result", v)) // d.taoLogger.Log.Debug("GetRecipe01ByProductCode", zap.Any("productCode", productCode), zap.Any("result", v))
return v, nil return v, nil
@ -290,38 +389,44 @@ func (d *Data) GetMaterialSetting(countryID, filename string) []models.MaterialS
result := make([]models.MaterialSetting, 0) result := make([]models.MaterialSetting, 0)
if countryID == "" { if countryID == "" {
copy(result, d.currentRecipe.MaterialSetting) copy(result, d.currentRecipe[countryID].MaterialSetting)
return result return result
} }
if !strings.Contains(filename, "tmp") { if !strings.Contains(filename, "tmp") {
if filename == "" || filename == d.CurrentFile { if filename == "" || filename == d.CurrentFile[countryID] {
copy(result, d.currentRecipe.MaterialSetting) // copy(result, d.currentRecipe[countryID].MaterialSetting)
d.taoLogger.Log.Debug("GetMaterialSetting", zap.Any("result", result)) // d.taoLogger.Log.Debug("GetMaterialSetting", zap.Any("result", result))
return d.currentRecipe.MaterialSetting return d.currentRecipe[countryID].MaterialSetting
} }
if recipe, ok := d.recipeMap[filename]; ok { if recipe, ok := d.recipeMap[filename]; ok {
copy(result, recipe.Recipe.MaterialSetting) copy(result, recipe.Recipe[countryID].MaterialSetting)
d.CurrentFile = filename d.CurrentFile[countryID] = filename
d.CurrentCountryID = countryID // d.CurrentCountryID[countryID] = countryID
return d.currentRecipe.MaterialSetting return d.currentRecipe[countryID].MaterialSetting
} }
} }
d.CurrentFile = filename if filename == "default" {
d.CurrentCountryID = countryID filename = d.CurrentFile[countryID]
}
// d.taoLogger.Log.Debug("GetMaterialSetting", zap.Any("filename", filename), zap.Any("countryID", countryID))
// d.CurrentFile[countryID] = filename
// d.CurrentCountryID[countryID] = countryID
recipe, err := helpers.ReadRecipeFile(countryID, filename) recipe, err := helpers.ReadRecipeFile(countryID, filename)
if err != nil { if err != nil {
d.taoLogger.Log.Error("Error when read recipe file, Return default recipe", zap.Error(err)) d.taoLogger.Log.Error("GetMaterialSetting: Error when read recipe file, Return default recipe", zap.Error(err))
copy(result, d.currentRecipe.MaterialSetting) copy(result, d.currentRecipe[countryID].MaterialSetting)
return d.currentRecipe.MaterialSetting return d.currentRecipe[countryID].MaterialSetting
} }
d.taoLogger.Log.Debug("GetMaterialSetting", zap.Any("recipe", recipe.MaterialSetting)) // d.taoLogger.Log.Debug("GetMaterialSetting", zap.Any("recipe", recipe.MaterialSetting))
d.currentRecipe = recipe d.currentRecipe[countryID] = recipe
// save to map // save to map
if len(d.recipeMap) > 5 { // limit keep in memory 5 version if len(d.recipeMap) > 5 { // limit keep in memory 5 version
@ -338,7 +443,7 @@ func (d *Data) GetMaterialSetting(countryID, filename string) []models.MaterialS
} }
d.recipeMap[filename] = RecipeWithTimeStamps{ d.recipeMap[filename] = RecipeWithTimeStamps{
Recipe: *d.currentRecipe, Recipe: d.currentRecipe,
TimeStamps: time.Now().Unix(), TimeStamps: time.Now().Unix(),
} }
@ -349,22 +454,27 @@ func (d *Data) GetMaterialSetting(countryID, filename string) []models.MaterialS
func (d *Data) GetMaterialCode(ids []uint64, countryID, filename string) []models.MaterialCode { func (d *Data) GetMaterialCode(ids []uint64, countryID, filename string) []models.MaterialCode {
var result []models.MaterialCode var result []models.MaterialCode
if filename == "" || filename == d.CurrentFile { if filename == "" || filename == d.CurrentFile[countryID] {
result = d.currentRecipe.MaterialCode result = d.currentRecipe[countryID].MaterialCode
} else if recipe, ok := d.recipeMap[filename]; ok { } else if recipe, ok := d.recipeMap[filename]; ok {
d.CurrentFile = filename d.CurrentFile[countryID] = filename
return recipe.Recipe.MaterialCode return recipe.Recipe[countryID].MaterialCode
} else { } else {
d.CurrentFile = filename
d.CurrentCountryID = countryID if filename == "default" {
filename = d.CurrentFile[countryID]
}
// d.CurrentFile[countryID] = filename
// d.CurrentCountryID[countryID] = countryID
recipe, err := helpers.ReadRecipeFile(countryID, filename) recipe, err := helpers.ReadRecipeFile(countryID, filename)
if err != nil { if err != nil {
d.taoLogger.Log.Error("Error when read recipe file, Return default recipe", zap.Error(err)) d.taoLogger.Log.Error("GetMaterialCode: Error when read recipe file, Return default recipe", zap.Error(err))
return d.currentRecipe.MaterialCode return d.currentRecipe[countryID].MaterialCode
} }
d.currentRecipe = recipe d.currentRecipe[countryID] = recipe
// save to map // save to map
if len(d.recipeMap) > 5 { // limit keep in memory 5 version if len(d.recipeMap) > 5 { // limit keep in memory 5 version
@ -381,11 +491,11 @@ func (d *Data) GetMaterialCode(ids []uint64, countryID, filename string) []model
} }
d.recipeMap[filename] = RecipeWithTimeStamps{ d.recipeMap[filename] = RecipeWithTimeStamps{
Recipe: *d.currentRecipe, Recipe: d.currentRecipe,
TimeStamps: time.Now().Unix(), TimeStamps: time.Now().Unix(),
} }
result = d.currentRecipe.MaterialCode result = d.currentRecipe[countryID].MaterialCode
} }
if len(ids) == 0 { if len(ids) == 0 {
@ -411,31 +521,41 @@ func (d *Data) GetMaterialCode(ids []uint64, countryID, filename string) []model
func (d *Data) GetToppings(countryID, filename string) models.Topping { func (d *Data) GetToppings(countryID, filename string) models.Topping {
if filename == "" || filename == d.CurrentFile { if filename == "" || filename == d.CurrentFile[countryID] {
return d.currentRecipe.Topping return d.currentRecipe[countryID].Topping
} else if recipe, ok := d.recipeMap[filename]; ok { } else if recipe, ok := d.recipeMap[filename]; ok {
d.CurrentFile = filename d.CurrentFile[countryID] = filename
return recipe.Recipe.Topping return recipe.Recipe[countryID].Topping
} }
d.CurrentFile = filename
d.CurrentCountryID = countryID if filename == "default" {
filename = d.CurrentFile[countryID]
}
// d.CurrentFile[countryID] = filename
// d.CurrentCountryID[countryID] = countryID
recipe, err := helpers.ReadRecipeFile(countryID, filename) recipe, err := helpers.ReadRecipeFile(countryID, filename)
if err != nil { if err != nil {
d.taoLogger.Log.Error("Error when read recipe file, Return default recipe", zap.Error(err)) d.taoLogger.Log.Error("GetToppings: Error when read recipe file, Return default recipe", zap.Error(err))
return d.currentRecipe.Topping return d.currentRecipe[countryID].Topping
} }
d.currentRecipe = recipe d.currentRecipe[countryID] = recipe
return recipe.Topping return recipe.Topping
} }
func (d *Data) GetToppingsOfRecipe(countryID, filename string, productCode string) ([]models.ToppingSet, error) { func (d *Data) GetToppingsOfRecipe(countryID, filename string, productCode string) ([]models.ToppingSet, error) {
if filename == "default" {
filename = d.CurrentFile[countryID]
}
recipe, err := d.GetRecipe01ByProductCode(filename, countryID, productCode) recipe, err := d.GetRecipe01ByProductCode(filename, countryID, productCode)
if err != nil { if err != nil {
d.taoLogger.Log.Error("Error when read recipe file, Return default recipe", zap.Error(err)) d.taoLogger.Log.Error("GetToppingOfRecipe: Error when read recipe file, Return default recipe", zap.Error(err))
return []models.ToppingSet{}, err return []models.ToppingSet{}, err
} }
@ -443,10 +563,15 @@ func (d *Data) GetToppingsOfRecipe(countryID, filename string, productCode strin
} }
func (d *Data) GetSubmenusOfRecipe(countryID, filename, productCode string) ([]models.Recipe01, error) { func (d *Data) GetSubmenusOfRecipe(countryID, filename, productCode string) ([]models.Recipe01, error) {
if filename == "default" {
filename = d.CurrentFile[countryID]
}
recipe, err := d.GetRecipe01ByProductCode(filename, countryID, productCode) recipe, err := d.GetRecipe01ByProductCode(filename, countryID, productCode)
if err != nil { if err != nil {
d.taoLogger.Log.Error("Error when read recipe file, Return default recipe", zap.Error(err)) d.taoLogger.Log.Error("GetSubmenusOfRecipe: Error when read recipe file, Return default recipe", zap.Error(err))
return []models.Recipe01{}, err return []models.Recipe01{}, err
} }

View file

@ -1,11 +1,23 @@
package data package data
import ( import (
"fmt"
"os"
"github.com/jmoiron/sqlx" "github.com/jmoiron/sqlx"
_ "github.com/mattn/go-sqlite3" _ "github.com/mattn/go-sqlite3"
) )
func NewSqliteDatabase() *sqlx.DB { func NewSqliteDatabase() *sqlx.DB {
// ensure that database exists
info, err := os.Stat("./data/database.db")
if os.IsNotExist(err) {
fmt.Println("No database found. Check path: ", err)
} else {
fmt.Println("Database existed. ", info)
}
db := sqlx.MustConnect("sqlite3", "./data/database.db") db := sqlx.MustConnect("sqlite3", "./data/database.db")
return db return db
} }

View file

@ -75,17 +75,7 @@ func (mr *MaterialRouter) GetFullMaterialDetail(w http.ResponseWriter, r *http.R
}) })
} }
// for _, matCode := range matCodes { mr.taoLogger.Log.Debug("GetFullMaterialDetail", zap.Any("materialDetails", materialDetails[0]))
// for index, matDetail := range materialDetails {
// if matCode.MaterialID == matDetail["materialId"] {
// materialDetails[index]["name"] = matCode.PackageDescription
// } else if matDetail["materialId"].(uint64) > 8110 && matDetail["materialId"].(uint64) <= 8130 {
// slotNum := matDetail["materialId"].(uint64) - 8110
// // mr.taoLogger.Log.Debug("GetFullMaterialDetail", zap.Any("slotNum", matDetail["materialId"]), zap.Any("slotNum", slotNum))
// materialDetails[index]["name"] = "Topping" + strconv.Itoa(int(slotNum))
// }
// }
// }
// send result // send result
if err := json.NewEncoder(w).Encode(materialDetails); err != nil { if err := json.NewEncoder(w).Encode(materialDetails); err != nil {
@ -141,7 +131,7 @@ func (mr *MaterialRouter) getMaterialSettingByMatID(w http.ResponseWriter, r *ht
countryID, err := mr.data.GetCountryIDByName(country) countryID, err := mr.data.GetCountryIDByName(country)
if err != nil { if err != nil {
mr.taoLogger.Log.Error("MaterialRouter.GetMaterialSettingByMatID", zap.Error(err)) // mr.taoLogger.Log.Error("MaterialRouter.GetMaterialSettingByMatID", zap.Error(err))
http.Error(w, "Country not found", http.StatusNotFound) http.Error(w, "Country not found", http.StatusNotFound)
return return
} }
@ -152,7 +142,7 @@ func (mr *MaterialRouter) getMaterialSettingByMatID(w http.ResponseWriter, r *ht
matIDuint, err := strconv.ParseUint(matID, 10, 64) matIDuint, err := strconv.ParseUint(matID, 10, 64)
if err != nil { if err != nil {
mr.taoLogger.Log.Error("MaterialRouter.GetMaterialSettingByMatID", zap.Error(err)) // mr.taoLogger.Log.Error("MaterialRouter.GetMaterialSettingByMatID", zap.Error(err))
http.Error(w, "Invalid material id", http.StatusBadRequest) http.Error(w, "Invalid material id", http.StatusBadRequest)
return return
} }
@ -167,7 +157,7 @@ func (mr *MaterialRouter) getMaterialSettingByMatID(w http.ResponseWriter, r *ht
} }
if err := json.NewEncoder(w).Encode(matSetting); err != nil { if err := json.NewEncoder(w).Encode(matSetting); err != nil {
mr.taoLogger.Log.Error("MaterialRouter.GetMaterialSettingByMatID", zap.Error(err)) // mr.taoLogger.Log.Error("MaterialRouter.GetMaterialSettingByMatID", zap.Error(err))
http.Error(w, "Internal Error", http.StatusInternalServerError) http.Error(w, "Internal Error", http.StatusInternalServerError)
return return
} }

View file

@ -173,6 +173,8 @@ func (rr *RecipeRouter) dashBoard(w http.ResponseWriter, r *http.Request) {
country := r.URL.Query().Get("country") country := r.URL.Query().Get("country")
filename := r.URL.Query().Get("filename") filename := r.URL.Query().Get("filename")
rr.taoLogger.Log.Debug("RecipeRouter.Dashboard", zap.Any("country", country), zap.Any("filename", filename))
result, err := rr.recipeService.GetRecipeDashboard(&contracts.RecipeDashboardRequest{ result, err := rr.recipeService.GetRecipeDashboard(&contracts.RecipeDashboardRequest{
Country: country, Country: country,
Filename: filename, Filename: filename,
@ -205,6 +207,8 @@ func (rr *RecipeRouter) overview(w http.ResponseWriter, r *http.Request) {
filename := r.URL.Query().Get("filename") filename := r.URL.Query().Get("filename")
materialIds := r.URL.Query().Get("materialIds") materialIds := r.URL.Query().Get("materialIds")
rr.taoLogger.Log.Debug("RecipeRouter.Overview", zap.Any("take", take), zap.Any("offset", offset), zap.Any("country", country), zap.Any("filename", filename), zap.Any("materialIds", materialIds))
var materialIdsUint []int var materialIdsUint []int
for _, v := range strings.Split(materialIds, ",") { for _, v := range strings.Split(materialIds, ",") {
materialIdUint, err := strconv.ParseUint(v, 10, 64) materialIdUint, err := strconv.ParseUint(v, 10, 64)

View file

@ -67,7 +67,7 @@ func (rs *recipeService) GetRecipeDetailMat(request *contracts.RecipeDetailReque
return contracts.RecipeDetailMatListResponse{}, fmt.Errorf("country name: %s not found", request.Country) return contracts.RecipeDetailMatListResponse{}, fmt.Errorf("country name: %s not found", request.Country)
} }
// rs.taoLogger.Log.Debug("GetRecipeDetailMat", zap.Any("request", request)) rs.taoLogger.Log.Debug("GetRecipeDetailMat", zap.Any("request", request))
recipe, err := rs.db.GetRecipe01ByProductCode(request.Filename, request.Country, request.ProductCode) recipe, err := rs.db.GetRecipe01ByProductCode(request.Filename, request.Country, request.ProductCode)
@ -186,6 +186,16 @@ func (rs *recipeService) GetRecipeDashboard(request *contracts.RecipeDashboardRe
recipe := rs.db.GetRecipe(countryID, request.Filename) recipe := rs.db.GetRecipe(countryID, request.Filename)
// recheck if filename is `default`
if request.Filename == "default" {
for _, v := range rs.db.DefaultCountryMap {
if v.CountryShortName == request.Country || v.CountryLongName == request.Country {
request.Filename = rs.db.CurrentFile[v.CountryShortName]
}
}
}
result := contracts.RecipeDashboardResponse{ result := contracts.RecipeDashboardResponse{
ConfigNumber: recipe.MachineSetting.ConfigNumber, ConfigNumber: recipe.MachineSetting.ConfigNumber,
LastUpdated: recipe.Timestamp, LastUpdated: recipe.Timestamp,