package postal_code import ( "cargo-erp-backend/internal/domain" "cargo-erp-backend/pkg/helpers" "cargo-erp-backend/pkg/importer" "fmt" "strings" "time" "gorm.io/gorm" ) type PostalCodeImportHandler struct { UserData domain.User Helper helpers.HelperInterface lastProvinceName string lastCityName string lastDistrictName string lastSubdistrictName string } func NewPostalCodeImportHandler(userData domain.User, helper helpers.HelperInterface) importer.ImportHandler { return &PostalCodeImportHandler{ UserData: userData, Helper: helper, } } func (h *PostalCodeImportHandler) ValidateRow(row []string, rowNumber int) (importer.RowData, []error) { var errors []error if len(row) < 5 { errors = append(errors, fmt.Errorf("row must have 5 columns: postal_code, subdistrict_name, district_name, city_name, province_name")) return nil, errors } postalCode := strings.TrimSpace(row[0]) if postalCode == "" { errors = append(errors, fmt.Errorf("postal_code is required")) } else if len(postalCode) > 10 { errors = append(errors, fmt.Errorf("postal_code must be at most 10 characters")) } subdistrictName := strings.TrimSpace(row[1]) if subdistrictName == "" { errors = append(errors, fmt.Errorf("subdistrict_name is required")) } districtName := strings.TrimSpace(row[2]) if districtName == "" { errors = append(errors, fmt.Errorf("district_name is required")) } cityName := strings.TrimSpace(row[3]) if cityName == "" { errors = append(errors, fmt.Errorf("city_name is required")) } provinceName := strings.TrimSpace(row[4]) if provinceName == "" { errors = append(errors, fmt.Errorf("province_name is required")) } if len(errors) > 0 { return nil, errors } var province domain.Province db := h.Helper.GetDB("slave") if err := db.Where("UPPER(name) = ?", strings.ToUpper(provinceName)).First(&province).Error; err != nil { errors = append(errors, fmt.Errorf("province '%s' not found", provinceName)) return nil, errors } var city domain.City if err := db.Where("UPPER(name) = ? AND province_id = ?", strings.ToUpper(cityName), province.ID).First(&city).Error; err != nil { errors = append(errors, fmt.Errorf("city '%s' not found in province '%s'", cityName, provinceName)) return nil, errors } var district domain.District if err := db.Where("UPPER(name) = ? AND city_id = ?", strings.ToUpper(districtName), city.ID).First(&district).Error; err != nil { errors = append(errors, fmt.Errorf("district '%s' not found in city '%s'", districtName, cityName)) return nil, errors } var subdistrict domain.Subdistrict if err := db.Where("UPPER(name) = ? AND district_id = ?", strings.ToUpper(subdistrictName), district.ID).First(&subdistrict).Error; err != nil { errors = append(errors, fmt.Errorf("subdistrict '%s' not found in district '%s'", subdistrictName, districtName)) return nil, errors } h.lastProvinceName = provinceName h.lastCityName = cityName h.lastDistrictName = districtName h.lastSubdistrictName = subdistrictName now := time.Now() nowStr := now.Format("2006-01-02 15:04:05.999999-07:00") pc := &domain.PostalCode{ PostalCode: &postalCode, ProvinceID: &province.ID, CityID: &city.ID, DistrictID: &district.ID, SubdistrictID: &subdistrict.ID, MerchantID: h.UserData.MerchantID, CreatedBy: &h.UserData.ID, CreatedOn: &now, UpdatedBy: &h.UserData.ID, UpdatedOn: &nowStr, } return pc, nil } func (h *PostalCodeImportHandler) GetDataString(data importer.RowData) string { pc := data.(*domain.PostalCode) code := "" if pc.PostalCode != nil { code = *pc.PostalCode } return fmt.Sprintf("%s, %s, %s, %s, %s", code, h.lastSubdistrictName, h.lastDistrictName, h.lastCityName, h.lastProvinceName) } func (h *PostalCodeImportHandler) IsDuplicate(db *gorm.DB, data importer.RowData) bool { pc := data.(*domain.PostalCode) var count int64 db.Model(&domain.PostalCode{}). Joins("JOIN subdistrict ON postal_code.subdistrict_id = subdistrict.id"). Joins("JOIN district ON postal_code.district_id = district.id"). Joins("JOIN city ON postal_code.city_id = city.id"). Joins("JOIN province ON postal_code.province_id = province.id"). Where("UPPER(postal_code.postal_code) = ? AND UPPER(subdistrict.name) = ? AND UPPER(district.name) = ? AND UPPER(city.name) = ? AND UPPER(province.name) = ?", strings.ToUpper(*pc.PostalCode), strings.ToUpper(h.lastSubdistrictName), strings.ToUpper(h.lastDistrictName), strings.ToUpper(h.lastCityName), strings.ToUpper(h.lastProvinceName)). Count(&count) return count > 0 } func (h *PostalCodeImportHandler) GetTemplateHeaders() []string { return []string{"postal_code", "subdistrict_name", "district_name", "city_name", "province_name"} } func (h *PostalCodeImportHandler) GetTemplateRows() [][]string { return [][]string{ {"10430", "Kramat Pulo", "Jakarta Pusat", "Jakarta Pusat", "DKI Jakarta"}, {"10430", "Senen", "Jakarta Pusat", "Jakarta Pusat", "DKI Jakarta"}, {"10440", "Cempaka Putih", "Jakarta Pusat", "Jakarta Pusat", "DKI Jakarta"}, {"10510", "Gambir", "Jakarta Pusat", "Jakarta Pusat", "DKI Jakarta"}, } }