Add material code and settings
This commit is contained in:
parent
36be0426f6
commit
498bcf1c24
9 changed files with 279 additions and 60 deletions
|
|
@ -3,7 +3,8 @@ export interface Recipe {
|
|||
MachineSetting: MachineSetting;
|
||||
Recipe01: Recipe01[];
|
||||
Topping: Topping;
|
||||
MaterailCode: MaterailCode[];
|
||||
MaterialCode: MaterialCode[];
|
||||
MaterialSetting: MaterialSetting[];
|
||||
}
|
||||
|
||||
export interface MachineSetting {
|
||||
|
|
@ -14,10 +15,10 @@ export interface MachineSetting {
|
|||
temperatureMin: string;
|
||||
}
|
||||
|
||||
export interface MaterailCode {
|
||||
export interface MaterialCode {
|
||||
PackageDescription: string;
|
||||
RefillValuePerStep: string;
|
||||
materialID: string;
|
||||
materialID: number;
|
||||
materialCode: string;
|
||||
}
|
||||
|
||||
|
|
@ -25,7 +26,7 @@ export interface Recipe01 {
|
|||
Description: string;
|
||||
ExtendID: string;
|
||||
OnTOP: string;
|
||||
LastChange: string;
|
||||
LastChange: Date;
|
||||
MenuStatus: string;
|
||||
RemainingCups: string;
|
||||
StringParam: string;
|
||||
|
|
@ -97,8 +98,8 @@ export interface MatRecipe {
|
|||
MixOrder: string;
|
||||
FeedParameter: string;
|
||||
FeedPattern: string;
|
||||
isUse: string;
|
||||
materialPathId: string;
|
||||
isUse: boolean;
|
||||
materialPathId: number;
|
||||
powderGram: string;
|
||||
powderTime: string;
|
||||
stirTime: string;
|
||||
|
|
|
|||
41
client/src/app/core/services/material.service.ts
Normal file
41
client/src/app/core/services/material.service.ts
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
import { HttpClient } from '@angular/common/http';
|
||||
import { Injectable } from '@angular/core';
|
||||
import { MaterialCode, MaterialSetting } from '../models/recipe.model';
|
||||
import { environment } from 'src/environments/environment';
|
||||
import { Observable } from 'rxjs';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class MaterialService {
|
||||
constructor(private _httpClient: HttpClient) {}
|
||||
|
||||
getMaterialCodes(
|
||||
matIds?: number[],
|
||||
version?: string
|
||||
): Observable<MaterialCode[]> {
|
||||
return this._httpClient.get<MaterialCode[]>(
|
||||
`${environment.api}/materials/code`,
|
||||
{
|
||||
params: {
|
||||
version: version || '',
|
||||
mat_ids: matIds?.join(',') || '',
|
||||
},
|
||||
withCredentials: true,
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
getMaterialSettingById(
|
||||
id: number,
|
||||
version?: string
|
||||
): Observable<MaterialSetting> {
|
||||
return this._httpClient.get<MaterialSetting>(
|
||||
`${environment.api}/materials/setting/${id}`,
|
||||
{
|
||||
params: {
|
||||
version: version || '',
|
||||
},
|
||||
withCredentials: true,
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -4,20 +4,23 @@
|
|||
class="block col-span-1 p-6 bg-white border border-gray-200 rounded-lg shadow"
|
||||
>
|
||||
<div *ngIf="isLoaded; else indicator" [@inOutAnimation]>
|
||||
<h5 class="mb-2 text-xl font-bold text-gray-900">
|
||||
{{ originalRecipeDetail?.name }} |
|
||||
{{ originalRecipeDetail?.productCode }}
|
||||
</h5>
|
||||
<div class="flex flex-wrap">
|
||||
<h5 class="mb-2 text-xl font-bold text-gray-900">
|
||||
{{ originalRecipeDetail.name }}
|
||||
</h5>
|
||||
<h5 class="mb-2 px-3 text-xl font-bold text-gray-900">|</h5>
|
||||
<h5 class="mb-2 text-xl font-bold text-gray-900">
|
||||
{{ originalRecipeDetail.productCode }}
|
||||
</h5>
|
||||
</div>
|
||||
<div class="flex items-center mb-2">
|
||||
<div class="flex items-center mr-4">
|
||||
<p class="text-sm text-gray-500">สูตร</p>
|
||||
<p class="ml-2 text-sm text-gray-900">
|
||||
{{ originalRecipeDetail?.name }}
|
||||
</p>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<p class="text-sm text-gray-500">ประเภท</p>
|
||||
<p class="ml-2 text-sm text-gray-900">เครื่องดื่ม</p>
|
||||
<p class="text-sm text-gray-500">Last Modify</p>
|
||||
<p class="ml-2 text-sm text-gray-900">
|
||||
{{
|
||||
originalRecipeDetail.lastModified | date : "dd/MM/yyyy HH:mm:ss"
|
||||
}}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex p-3 items-center justify-center w-full">
|
||||
|
|
@ -103,26 +106,38 @@
|
|||
</div>
|
||||
</ng-template>
|
||||
</div>
|
||||
<div
|
||||
class="flex items-center justify-center h-48 mb-4 rounded bg-gray-50 dark:bg-gray-800"
|
||||
>
|
||||
<p class="text-2xl text-gray-400 dark:text-gray-500">
|
||||
<svg
|
||||
class="w-3.5 h-3.5"
|
||||
aria-hidden="true"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 18 18"
|
||||
>
|
||||
<path
|
||||
stroke="currentColor"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M9 1v16M1 9h16"
|
||||
/>
|
||||
</svg>
|
||||
</p>
|
||||
<div class="col-span-3 max-h-[300px] overflow-auto mb-4 rounded">
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr class="bg-gray-200">
|
||||
<th class="px-6 py-3">Enable</th>
|
||||
<th class="px-6 py-3">Material ID</th>
|
||||
<th class="px-6 py-3">Material Name</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody *ngIf="isMatLoaded; else indicator">
|
||||
<tr
|
||||
*ngFor="let mat of originalRecipeDetail?.matData"
|
||||
class="bg-white la border-b hover:bg-secondary"
|
||||
>
|
||||
<td class="px-6 py-4 font-medium text-gray-900 whitespace-nowrap">
|
||||
<label>
|
||||
<input
|
||||
type="checkbox"
|
||||
class="toggle toggle-sm"
|
||||
[checked]="mat.enable"
|
||||
/>
|
||||
</label>
|
||||
</td>
|
||||
<td class="px-6 py-4 font-medium text-gray-900 whitespace-nowrap">
|
||||
{{ mat.id }}
|
||||
</td>
|
||||
<td class="px-6 py-4 font-medium text-gray-900 whitespace-nowrap">
|
||||
{{ mat.name }}
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="grid grid-cols-2 gap-4 mb-4">
|
||||
<div
|
||||
|
|
@ -318,7 +333,7 @@
|
|||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="sticky bottom-0 col-span-3 flex justify-end bg-white rounded-full shadow-xl p-3"
|
||||
class="sticky bottom-0 col-span-3 flex justify-end bg-white rounded-full drop-shadow-2xl p-3"
|
||||
>
|
||||
<button
|
||||
(click)="onPressConfirmClose()"
|
||||
|
|
|
|||
|
|
@ -1,15 +1,18 @@
|
|||
import { NgIf } from '@angular/common';
|
||||
import { DatePipe, NgFor, NgIf } from '@angular/common';
|
||||
import { Component, EventEmitter, OnInit } from '@angular/core';
|
||||
import { FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms';
|
||||
import { ActivatedRoute, Router, RouterLink } from '@angular/router';
|
||||
import { isEqual } from 'lodash';
|
||||
import { delay } from 'rxjs';
|
||||
import { delay, finalize } from 'rxjs';
|
||||
import { RecipeService } from 'src/app/core/services/recipe.service';
|
||||
import { ConfirmModal } from 'src/app/shared/modal/confirm/confirm-modal.component';
|
||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
||||
import { animate, style, transition, trigger } from '@angular/animations';
|
||||
import { MatRecipe } from 'src/app/core/models/recipe.model';
|
||||
import { MaterialService } from 'src/app/core/services/material.service';
|
||||
|
||||
interface RecipeDetail {
|
||||
lastModified: Date;
|
||||
productCode: string;
|
||||
name: string;
|
||||
otherName: string;
|
||||
|
|
@ -19,6 +22,14 @@ interface RecipeDetail {
|
|||
isUse: boolean;
|
||||
isShow: boolean;
|
||||
disable: boolean;
|
||||
recipes: MatRecipe[];
|
||||
matData?: MaterialData[];
|
||||
}
|
||||
|
||||
interface MaterialData {
|
||||
id: number;
|
||||
name: string;
|
||||
enable: boolean;
|
||||
}
|
||||
|
||||
interface RecipeMetaData {
|
||||
|
|
@ -34,7 +45,14 @@ interface RecipeMetaData {
|
|||
selector: 'app-recipe-details',
|
||||
templateUrl: './recipe-details.component.html',
|
||||
standalone: true,
|
||||
imports: [NgIf, RouterLink, ReactiveFormsModule, ConfirmModal],
|
||||
imports: [
|
||||
NgIf,
|
||||
NgFor,
|
||||
RouterLink,
|
||||
ReactiveFormsModule,
|
||||
ConfirmModal,
|
||||
DatePipe,
|
||||
],
|
||||
animations: [
|
||||
trigger('inOutAnimation', [
|
||||
transition(':enter', [
|
||||
|
|
@ -48,14 +66,16 @@ export class RecipeDetailsComponent implements OnInit {
|
|||
title: string = 'Recipe Detail';
|
||||
recipeMetaData: RecipeMetaData | null = null;
|
||||
|
||||
originalRecipeDetail: RecipeDetail | null = null;
|
||||
originalRecipeDetail!: RecipeDetail;
|
||||
|
||||
isLoaded: boolean = false;
|
||||
isMatLoaded: boolean = false;
|
||||
|
||||
constructor(
|
||||
private _route: ActivatedRoute,
|
||||
private _router: Router,
|
||||
private _recipeService: RecipeService
|
||||
private _recipeService: RecipeService,
|
||||
private _materialService: MaterialService
|
||||
) {}
|
||||
|
||||
recipeDetail = new FormGroup({
|
||||
|
|
@ -73,6 +93,7 @@ export class RecipeDetailsComponent implements OnInit {
|
|||
ngOnInit() {
|
||||
this._recipeService
|
||||
.getRecipesById(this._route.snapshot.params['productCode'])
|
||||
.pipe(finalize(() => {}))
|
||||
.subscribe(({ recipe, recipeMetaData }) => {
|
||||
this.title = recipe.name + ' | ' + recipe.productCode;
|
||||
this.recipeDetail.patchValue({
|
||||
|
|
@ -87,6 +108,7 @@ export class RecipeDetailsComponent implements OnInit {
|
|||
disable: recipe.disable,
|
||||
});
|
||||
this.originalRecipeDetail = {
|
||||
lastModified: recipe.LastChange,
|
||||
productCode: recipe.productCode,
|
||||
name: recipe.name,
|
||||
otherName: recipe.otherName,
|
||||
|
|
@ -96,9 +118,27 @@ export class RecipeDetailsComponent implements OnInit {
|
|||
isUse: recipe.isUse,
|
||||
isShow: recipe.isShow,
|
||||
disable: recipe.disable,
|
||||
recipes: recipe.recipes,
|
||||
};
|
||||
this.recipeMetaData = recipeMetaData;
|
||||
this.isLoaded = true;
|
||||
|
||||
const ids = this.originalRecipeDetail.recipes.map(
|
||||
(recipe) => recipe.materialPathId
|
||||
);
|
||||
|
||||
this._materialService.getMaterialCodes(ids).subscribe((data) => {
|
||||
this.originalRecipeDetail.matData = data
|
||||
.map((item) => {
|
||||
return {
|
||||
id: item.materialID,
|
||||
name: item.PackageDescription,
|
||||
enable: false,
|
||||
};
|
||||
})
|
||||
.sort((a, b) => (a.id > b.id ? -1 : -1));
|
||||
this.isMatLoaded = true;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -84,12 +84,7 @@ export class DashboardComponent implements OnInit {
|
|||
);
|
||||
}
|
||||
|
||||
constructor(
|
||||
private _route: ActivatedRoute,
|
||||
private _router: Router,
|
||||
private _userService: UserService,
|
||||
private _recipeService: RecipeService
|
||||
) {}
|
||||
constructor(private _recipeService: RecipeService) {}
|
||||
|
||||
ngOnInit(): void {
|
||||
this._recipeService
|
||||
|
|
|
|||
|
|
@ -89,3 +89,49 @@ func (d *Data) GetRecipe(version string) models.Recipe {
|
|||
func (d *Data) GetRecipe01() []models.Recipe01 {
|
||||
return d.recipe.Recipe01
|
||||
}
|
||||
|
||||
func (d *Data) GetMaterialSetting(version string) []models.MaterialSetting {
|
||||
result := make([]models.MaterialSetting, 0)
|
||||
|
||||
if version == "" || version == d.CurrentVersion {
|
||||
copy(result, d.recipe.MaterialSetting)
|
||||
return result
|
||||
}
|
||||
|
||||
d.CurrentVersion = version
|
||||
d.recipe = readFile(version)
|
||||
copy(result, d.recipe.MaterialSetting)
|
||||
return result
|
||||
}
|
||||
|
||||
func (d *Data) GetMaterialCode(ids []uint64, version string) []models.MaterialCode {
|
||||
var result []models.MaterialCode
|
||||
|
||||
if version == "" || version == d.CurrentVersion {
|
||||
result = d.recipe.MaterialCode
|
||||
} else {
|
||||
d.CurrentVersion = version
|
||||
d.recipe = readFile(version)
|
||||
result = d.recipe.MaterialCode
|
||||
}
|
||||
|
||||
if len(ids) == 0 {
|
||||
return result
|
||||
}
|
||||
|
||||
resultFilter := make([]models.MaterialCode, len(ids))
|
||||
for _, id := range ids {
|
||||
if id == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
for _, m := range result {
|
||||
if m.MaterialID == id {
|
||||
resultFilter = append(resultFilter, m)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return resultFilter
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,14 +1,15 @@
|
|||
package models
|
||||
|
||||
type Recipe struct {
|
||||
Timestamp string `json:"Timestamp"`
|
||||
MachineSetting MatchineSetting `json:"MachineSetting"`
|
||||
Recipe01 []Recipe01 `json:"Recipe01"`
|
||||
Topping Topping `json:"Topping"`
|
||||
MaterailCode []MaterailCode `json:"MaterailCode"`
|
||||
Timestamp string `json:"Timestamp"`
|
||||
MachineSetting MachineSetting `json:"MachineSetting"`
|
||||
Recipe01 []Recipe01 `json:"Recipe01"`
|
||||
Topping Topping `json:"Topping"`
|
||||
MaterialCode []MaterialCode `json:"MaterialCode"`
|
||||
MaterialSetting []MaterialSetting `json:"MaterialSetting"`
|
||||
}
|
||||
|
||||
type MatchineSetting struct {
|
||||
type MachineSetting struct {
|
||||
RecipeTag string `json:"RecipeTag"`
|
||||
StrTextShowError []string `json:"strTextShowError"`
|
||||
ConfigNumber int `json:"configNumber"`
|
||||
|
|
@ -16,10 +17,10 @@ type MatchineSetting struct {
|
|||
TemperatureMin int `json:"temperatureMin"`
|
||||
}
|
||||
|
||||
type MaterailCode struct {
|
||||
type MaterialCode struct {
|
||||
PackageDescription string `json:"PackageDescription"`
|
||||
RefillValuePerStep int `json:"RefillValuePerStep"`
|
||||
MaterialID int `json:"materialID"`
|
||||
MaterialID uint64 `json:"materialID"`
|
||||
MaterialCode string `json:"materialCode"`
|
||||
}
|
||||
|
||||
|
|
@ -40,7 +41,7 @@ type MaterialSetting struct {
|
|||
SodaChannel bool `json:"SodaChannel"`
|
||||
StockAdjust int `json:"StockAdjust"`
|
||||
SyrupChannel bool `json:"SyrupChannel"`
|
||||
ID int `json:"id"`
|
||||
ID uint64 `json:"id"`
|
||||
IDAlternate int `json:"idAlternate"`
|
||||
IsUse bool `json:"isUse"`
|
||||
PayRettryMaxCount int `json:"pay_rettry_max_count"`
|
||||
|
|
|
|||
76
server/routers/material.go
Normal file
76
server/routers/material.go
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
package routers
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"recipe-manager/data"
|
||||
"recipe-manager/models"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/go-chi/chi/v5"
|
||||
)
|
||||
|
||||
type MaterialRouter struct {
|
||||
data *data.Data
|
||||
}
|
||||
|
||||
func NewMaterialRouter(data *data.Data) *MaterialRouter {
|
||||
return &MaterialRouter{
|
||||
data: data,
|
||||
}
|
||||
}
|
||||
|
||||
func (mr *MaterialRouter) Route(r chi.Router) {
|
||||
r.Route("/materials", func(r chi.Router) {
|
||||
r.Get("/code", func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Add("Content-Type", "application/json")
|
||||
|
||||
version := r.URL.Query().Get("version")
|
||||
|
||||
matIDs := r.URL.Query().Get("mat_ids")
|
||||
|
||||
var matIDsUint []uint64
|
||||
for _, v := range strings.Split(matIDs, ",") {
|
||||
matIDUint, err := strconv.ParseUint(v, 10, 64)
|
||||
|
||||
if err != nil || matIDUint == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
matIDsUint = append(matIDsUint, matIDUint)
|
||||
}
|
||||
|
||||
material := mr.data.GetMaterialCode(matIDsUint, version)
|
||||
|
||||
json.NewEncoder(w).Encode(material)
|
||||
})
|
||||
|
||||
r.Get("/setting/{mat_id}", func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Add("Content-Type", "application/json")
|
||||
|
||||
version := r.URL.Query().Get("version")
|
||||
|
||||
material := mr.data.GetMaterialSetting(version)
|
||||
|
||||
matID := chi.URLParam(r, "mat_id")
|
||||
|
||||
matIDuint, err := strconv.ParseUint(matID, 10, 64)
|
||||
if err != nil {
|
||||
http.Error(w, "Invalid material id", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
var matSetting models.MaterialSetting
|
||||
|
||||
for _, mat := range material {
|
||||
if mat.ID == matIDuint {
|
||||
matSetting = mat
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
json.NewEncoder(w).Encode(matSetting)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
|
@ -437,7 +437,6 @@ func (s *Server) createHandler() {
|
|||
Log.Debug("Scan dir completed < ", zap.String("path", r.RequestURI))
|
||||
})
|
||||
|
||||
// Recipe Router
|
||||
sheetService, err := sheet.NewSheetService(context.Background(), s.cfg)
|
||||
|
||||
if err != nil {
|
||||
|
|
@ -445,9 +444,14 @@ func (s *Server) createHandler() {
|
|||
return
|
||||
}
|
||||
|
||||
// Recipe Router
|
||||
rr := routers.NewRecipeRouter(database, sheetService)
|
||||
rr.Route(r)
|
||||
|
||||
// Material Router
|
||||
mr := routers.NewMaterialRouter(database)
|
||||
mr.Route(r)
|
||||
|
||||
})
|
||||
|
||||
r.NotFound(func(w http.ResponseWriter, r *http.Request) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue